@@ -64,6 +64,7 @@ services:
|
||||
volumes:
|
||||
- ./rocketmq/broker/logs:/home/rocketmq/logs
|
||||
- ./rocketmq/broker/store:/home/rocketmq/store
|
||||
- ./rocketmq/timerwheel:/home/rocketmq/timerwheel
|
||||
- ./rocketmq/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf
|
||||
- ./rocketmq/broker/conf/plain_acl.yml:/home/rocketmq/rocketmq-5.3.2/conf/plain_acl.yml
|
||||
depends_on:
|
||||
@@ -94,4 +95,24 @@ services:
|
||||
volumes:
|
||||
- /home/jenkins/work:/var/jenkins_home # 数据持久化
|
||||
- /var/run/docker.sock:/var/run/docker.sock # 宿主机 Docker 控制
|
||||
- /usr/bin/docker:/usr/bin/docker # 宿主机 Docker 命令
|
||||
- /usr/bin/docker:/usr/bin/docker # 宿主机 Docker 命令
|
||||
srs:
|
||||
image: ossrs/srs:5
|
||||
container_name: srs
|
||||
restart: always
|
||||
ports:
|
||||
- "1935:1935/tcp" # RTMP 推流
|
||||
- "1985:1985/tcp" # HTTP API
|
||||
- "7088:7088/tcp" # H5播放器/信令
|
||||
- "8000:8000/udp" # WebRTC媒体传输
|
||||
- "1989:1989/tcp" # WebRTC信令
|
||||
- "8443:8443/tcp" # HTTPS/WSS
|
||||
- "61100-61200:61100-61200/udp" # WebRTC动态端口范围
|
||||
environment:
|
||||
- CANDIDATE=192.168.1.37 # 公网ip
|
||||
- SRS_LISTEN=8000 # WebRTC监听端口
|
||||
- SRS_HTTP_SERVER_PORT=7088
|
||||
- SRS_HTTP_API_PORT=1985
|
||||
volumes:
|
||||
- "/home/docker/srs:/usr/local/srs/conf"
|
||||
command: [ "./objs/srs", "-c", "conf/srs_conf_7088.conf" ]
|
||||
@@ -2,10 +2,20 @@
|
||||
|
||||
上传目录下的docker文件夹到服务器/home/docker下面, 需要修改env文件夹rocketmq文件夹里面的配置, 特别是[broker.conf](docker/rocketmq/broker/conf/broker.conf)里面brokerIP1的值
|
||||
|
||||
```bash
|
||||
# 授权目录
|
||||
|
||||
mkdir /home/docker/rocketmq/broker/conf/ /home/docker/rocketmq/broker/logs/ /home/docker/rocketmq/broker/store/ -p
|
||||
|
||||
chmod 777 /home/docker/rocketmq/broker/conf/
|
||||
chmod 777 /home/docker/rocketmq/broker/logs/
|
||||
chmod 777 /home/docker/rocketmq/broker/store/
|
||||
chmod 777 /home/docker/rocketmq/timerwheel/
|
||||
```
|
||||
|
||||
## 🛠️ 启动命令
|
||||
- **仔细阅读**: docker-compose.yml 的内容(redis的密码也在这里面设置的)、./env 文件夹下面的内容,里面包含了账号密码等信息
|
||||
- **打开目录**: 当前文件夹下输入 cmd 回车
|
||||
- **执行命令**: docker-compose up -d
|
||||
- **导入nacos数据库**: [mysql-schema.sql](../mysql-schema.sql)
|
||||
- **导入nacos命名空间数据**: [nacos_config_export_20250816090745.zip](../../nacos/nacos_config_export_20250816090745.zip)
|
||||
- **导入nacos命名空间数据**: [nacos_config_export_20251019194635.zip](../nacos/nacos_config_export_20251019194635.zip)
|
||||
@@ -20,7 +20,7 @@ namesrvAddr=rocketmq-namesrv:9876
|
||||
|
||||
#启动IP,如果 docker 报 com.alibaba.rocketmq.remoting.exception.RemotingConnectException: connect to <192.168.0.120:10909> failed
|
||||
# 解决方式1 加上一句producer.setVipChannelEnabled(false);,解决方式2 brokerIP1 设置宿主机IP,不要使用docker 内部IP
|
||||
brokerIP1=rocketmq-broker
|
||||
brokerIP1=192.168.1.37
|
||||
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
|
||||
defaultTopicQueueNums=4
|
||||
|
||||
@@ -71,14 +71,19 @@ abortFile=/home/rocketmq/store/abort
|
||||
maxMessageSize=65536
|
||||
|
||||
# 延迟消息配置
|
||||
#timerWheelEnable=false
|
||||
#enableScheduleMessage=false
|
||||
|
||||
timerWheelEnable=true
|
||||
# 启用延迟消息功能
|
||||
enableScheduleMessage=true
|
||||
# 定义延迟级别
|
||||
messageDelayLevel=1s 3s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
|
||||
# 确保此目录存在且可写
|
||||
#timerStorePath=/home/rocketmq/store/timerwheel
|
||||
#timerFlushIntervalMs=1000
|
||||
#timerPrecisionMs=1000
|
||||
#scheduleMessageServiceThreadPoolNums=4
|
||||
timerStorePath=/home/docker/rocketmq/timerwheel
|
||||
# 时间轮刷新间隔
|
||||
timerFlushIntervalMs=1000
|
||||
# 时间轮精度
|
||||
timerPrecisionMs=1000
|
||||
# 调度消息服务线程数
|
||||
scheduleMessageServiceThreadPoolNums=4
|
||||
|
||||
#flushCommitLogLeastPages=4
|
||||
#flushConsumeQueueLeastPages=2
|
||||
|
||||
@@ -1,33 +1,64 @@
|
||||
# 基础运行配置
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
daemon off;
|
||||
srs_log_tank console;
|
||||
|
||||
# 低延迟优化
|
||||
vhost __defaultVhost__ {
|
||||
tcp_nodelay on;
|
||||
min_latency on;
|
||||
}
|
||||
|
||||
# HTTP API 服务(用于服务器状态管理)
|
||||
http_api {
|
||||
enabled on;
|
||||
listen 1985;
|
||||
crossdomain on;
|
||||
}
|
||||
|
||||
# HTTP 服务器(用于H5播放器拉流)
|
||||
http_server {
|
||||
enabled on;
|
||||
listen 7088;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
|
||||
# WebRTC 信令服务器配置
|
||||
rtc_server {
|
||||
enabled on;
|
||||
listen 8000;
|
||||
candidate 公网ip;
|
||||
listen 8000; # WebRTC信令端口
|
||||
candidate 192.168.1.37; # 公网IP
|
||||
}
|
||||
|
||||
# 虚拟主机配置
|
||||
vhost __defaultVhost__ {
|
||||
# WebRTC 模式配置
|
||||
rtc {
|
||||
enabled on;
|
||||
rtmp_to_rtc on;
|
||||
rtc_to_rtmp on;
|
||||
# 关闭 RTMP 转 WebRTC(避免强制中转,因为要实现P2P打视频)
|
||||
rtmp_to_rtc off; # on:表示支持RTMP推流转WebRTC播放
|
||||
rtc_to_rtmp off; # on:表示支持WebRTC推流转RTMP播放
|
||||
# P2P模式必须开启NACK
|
||||
nack on;
|
||||
# 开启TWCC带宽估计
|
||||
twcc on;
|
||||
}
|
||||
|
||||
# HTTP-FLV 流配置
|
||||
http_remux {
|
||||
enabled on;
|
||||
mount [vhost]/[app]/[stream].flv;
|
||||
mount [vhost]/webrtc/;
|
||||
}
|
||||
|
||||
# HLS 流配置(用于兼容性)
|
||||
hls {
|
||||
enabled off;
|
||||
}
|
||||
|
||||
# 低延迟播放配置
|
||||
play {
|
||||
gop_cache off; # 关闭GOP缓存降低延迟
|
||||
queue_length 10; # 减小播放队列长度
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,12 @@ no-tcp6
|
||||
cert=/etc/turn_server_cert.pem
|
||||
pkey=/etc/turn_server_pkey.pem
|
||||
dh-file=/etc/coturn/dhparam.pem
|
||||
|
||||
# 认证配置(使用长期凭证)
|
||||
verbose
|
||||
fingerprint
|
||||
lt-cred-mech
|
||||
|
||||
# Coturn TURN SERVER configuration file
|
||||
#
|
||||
# Boolean values note: where boolean value is supposed to be used,
|
||||
|
||||
@@ -77,7 +77,12 @@ turnserver -a -o -f -r hulaspark.com
|
||||
```
|
||||
|
||||
### 6. 测试服务
|
||||
测试地址:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
|
||||
|
||||
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
|
||||
host: 本地直连测试,用在局域网
|
||||
|
||||
srflx:公网直连也叫打洞测试,不过图中只有一个srflx返回,正常应该有两个
|
||||
|
||||
relay:是中继测试,我们这次测试意思就是我们所在网络使用中继模式才能成功
|
||||
|
||||

|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 28 KiB |
BIN
docs/install/image/login.png
Normal file
BIN
docs/install/image/login.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
BIN
docs/install/nacos/nacos_config_export_20251019194635.zip
Normal file
BIN
docs/install/nacos/nacos_config_export_20251019194635.zip
Normal file
Binary file not shown.
@@ -25,6 +25,7 @@ services:
|
||||
volumes:
|
||||
- ./rocketmq/broker/logs:/home/rocketmq/logs
|
||||
- ./rocketmq/broker/store:/home/rocketmq/store
|
||||
- ./rocketmq/timerwheel:/home/rocketmq/timerwheel
|
||||
- ./rocketmq/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf
|
||||
- ./rocketmq/broker/conf/plain_acl.yml:/home/rocketmq/rocketmq-5.3.2/conf/plain_acl.yml
|
||||
depends_on:
|
||||
|
||||
@@ -71,14 +71,19 @@ abortFile=/home/rocketmq/store/abort
|
||||
maxMessageSize=65536
|
||||
|
||||
# 延迟消息配置
|
||||
#timerWheelEnable=false
|
||||
#enableScheduleMessage=false
|
||||
|
||||
timerWheelEnable=true
|
||||
# 启用延迟消息功能
|
||||
enableScheduleMessage=true
|
||||
# 定义延迟级别
|
||||
messageDelayLevel=1s 3s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
|
||||
# 确保此目录存在且可写
|
||||
#timerStorePath=/home/rocketmq/store/timerwheel
|
||||
#timerFlushIntervalMs=1000
|
||||
#timerPrecisionMs=1000
|
||||
#scheduleMessageServiceThreadPoolNums=4
|
||||
timerStorePath=/home/docker/rocketmq/timerwheel
|
||||
# 时间轮刷新间隔
|
||||
timerFlushIntervalMs=1000
|
||||
# 时间轮精度
|
||||
timerPrecisionMs=1000
|
||||
# 调度消息服务线程数
|
||||
scheduleMessageServiceThreadPoolNums=4
|
||||
|
||||
#flushCommitLogLeastPages=4
|
||||
#flushConsumeQueueLeastPages=2
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
Target Server Version : 80030 (8.0.30)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 11/10/2025 18:27:50
|
||||
Date: 20/10/2025 17:27:06
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@@ -1126,15 +1126,6 @@ CREATE TABLE `def_login_log` (
|
||||
-- ----------------------------
|
||||
-- Records of def_login_log
|
||||
-- ----------------------------
|
||||
INSERT INTO `def_login_log` VALUES (83160717456896, NULL, NULL, NULL, '192.168.1.37', '', '1046762075', '04', '用户不存在!', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 11:31:00', NULL, '2025-10-11 11:31:00', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83160742622720, NULL, NULL, NULL, '192.168.1.37', '', 'Dawn', '04', '用户不存在!', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 11:31:06', NULL, '2025-10-11 11:31:06', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83160776177152, NULL, 10937855681024, 61170828519937, '192.168.1.37', 'Dawn', '2439646234', '01', '登录成功', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 11:31:15', 61170828519937, '2025-10-11 11:31:15', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83161032029696, NULL, 10937855681024, 61170828519937, '192.168.1.37', 'Dawn', '2439646234', '01', '登录成功', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 11:32:15', 61170828519937, '2025-10-11 11:32:15', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83162239989248, NULL, 10937855681024, 61170828519937, '192.168.1.37', 'Dawn', '2439646234', '01', '登录成功', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 11:37:04', 61170828519937, '2025-10-11 11:37:04', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83263746340352, NULL, NULL, NULL, '192.168.1.37', '', '1046762075', '04', '用户不存在!', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 18:20:24', NULL, '2025-10-11 18:20:24', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83265226929664, NULL, NULL, NULL, '192.168.1.37', '', '1046762075', '04', '用户不存在!', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 18:26:17', NULL, '2025-10-11 18:26:17', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83265235318272, NULL, NULL, NULL, '192.168.1.37', '', '1046762075', '04', '用户不存在!', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 18:26:20', NULL, '2025-10-11 18:26:20', NULL, 0);
|
||||
INSERT INTO `def_login_log` VALUES (83265403090432, NULL, 10937855681024, 61170828519937, '192.168.1.37', 'Dawn', '2439646234', '01', '登录成功', '2025-10-11', 'ReactorNetty/1.2.2', 'Unknown', '', 'Unknown', '0|0|0|内网IP|内网IP', '2025-10-11 18:27:00', 61170828519937, '2025-10-11 18:27:00', NULL, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for def_msg_template
|
||||
@@ -1802,7 +1793,7 @@ CREATE TABLE `def_user` (
|
||||
-- Records of def_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `def_user` VALUES (61170828519936, 2, 'bot', 'HuLa小管家', '', '022', NULL, NULL, '', NULL, b'0', '', '', '1', b'1', '', '2025-08-11 11:11:03.139', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"120.231.232.41\", \"createIpDetail\": null, \"updateIpDetail\": null}', '2025-08-19 10:05:05', 1, NULL, 'a4d5c225e6709ba025272a31c7e90e0121d5e5ba16695afe0b61370bedb677d0', 'Dawn', '2025-07-07 15:27:02', 1, '2025-03-27 04:23:08', NULL, '2025-07-16 12:26:15', 0, 1);
|
||||
INSERT INTO `def_user` VALUES (61170828519937, 2, '2439646234', 'Dawn', '2439646234@qq.com', 'https://cdn.hulaspark.com/avatar/2439646234/6ec99d37b8ba1296c325d2d36b46a14d.webp', NULL, NULL, '', NULL, b'0', '', '', '1', b'1', '', '2025-08-11 11:11:03.189', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"192.168.1.37\", \"createIpDetail\": null, \"updateIpDetail\": {\"ip\": \"192.168.1.37\", \"isp\": \"内网IP\", \"area\": \"\", \"city\": \"内网IP\", \"isp_id\": \"local\", \"region\": \"\", \"city_id\": \"local\", \"country\": \"\", \"region_id\": \"\", \"country_id\": \"\"}}', NULL, 0, NULL, 'a4d5c225e6709ba025272a31c7e90e0121d5e5ba16695afe0b61370bedb677d0', 'Dawn', '2025-10-11 18:27:00', 1, '2025-03-27 04:23:08', NULL, '2025-10-11 18:27:00', 0, 1);
|
||||
INSERT INTO `def_user` VALUES (61170828519937, 2, '2439646234', 'Dawn', '2439646234@qq.com', 'https://cdn.hulaspark.com/avatar/2439646234/6ec99d37b8ba1296c325d2d36b46a14d.webp', NULL, NULL, '', NULL, b'0', '', '', '1', b'1', '', '2025-08-11 11:11:03.189', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"192.168.1.26\", \"createIpDetail\": null, \"updateIpDetail\": {\"ip\": \"192.168.1.26\", \"isp\": \"内网IP\", \"area\": \"\", \"city\": \"内网IP\", \"isp_id\": \"local\", \"region\": \"\", \"city_id\": \"local\", \"country\": \"\", \"region_id\": \"\", \"country_id\": \"\"}}', NULL, 0, NULL, 'a4d5c225e6709ba025272a31c7e90e0121d5e5ba16695afe0b61370bedb677d0', 'Dawn', '2025-10-20 16:12:56', 1, '2025-03-27 04:23:08', NULL, '2025-10-20 16:25:36', 0, 1);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for def_user_application
|
||||
@@ -1887,7 +1878,7 @@ CREATE TABLE `extend_interface_log` (
|
||||
-- Records of extend_interface_log
|
||||
-- ----------------------------
|
||||
INSERT INTO `extend_interface_log` VALUES (66567882983426, 244439130119864323, '阿里短信', 0, 1, '2025-08-26 16:37:01', '2025-08-26 16:37:00', NULL, '2025-08-26 16:37:00', NULL, 0, 0);
|
||||
INSERT INTO `extend_interface_log` VALUES (655249535051914248, 244881451621810192, '腾讯邮件', 222, 37, '2025-10-10 09:11:17', '2025-07-16 18:41:01', NULL, '2025-07-16 18:41:01', NULL, 0, 0);
|
||||
INSERT INTO `extend_interface_log` VALUES (655249535051914248, 244881451621810192, '腾讯邮件', 340, 51, '2025-10-20 12:13:08', '2025-07-16 18:41:01', NULL, '2025-07-16 18:41:01', NULL, 0, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for extend_interface_logging
|
||||
@@ -2031,6 +2022,39 @@ CREATE TABLE `secure_invoke_record` (
|
||||
-- Records of secure_invoke_record
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_model
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_model`;
|
||||
CREATE TABLE `sys_model` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`model_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模型唯一键',
|
||||
`model_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模型名称',
|
||||
`model_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模型文件URL',
|
||||
`description` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '模型描述',
|
||||
`version` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模型版本号',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:0-禁用,1-启用',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 1 COMMENT '租户ID',
|
||||
`is_del` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||
`create_by` bigint NOT NULL DEFAULT 1 COMMENT '创建者',
|
||||
`update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uk_model_key`(`model_key` ASC) USING BTREE,
|
||||
INDEX `idx_model_name`(`model_name` ASC) USING BTREE,
|
||||
INDEX `idx_status`(`status` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统模型表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_model
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_model` VALUES (1, 'hula-20251022', 'HuLa_模型', 'https://cdn.hulaspark.com/models/hula.glb', 'HuLa 模型基础模型', '20251022', 1, '2025-10-20 04:09:29', '2025-10-20 06:08:10', 1, 0, 1, NULL);
|
||||
INSERT INTO `sys_model` VALUES (2, 't1_yongen', 't1_永恩', 'https://cdn.hulaspark.com/models/t1_%E6%B0%B8%E6%81%A9.glb', 'T1战队主题永恩模型', '20251022', 1, '2025-10-20 06:00:24', NULL, 1, 0, 1, NULL);
|
||||
INSERT INTO `sys_model` VALUES (3, 'sea_devil_aatrox', '海魔至尊_亚托克斯', 'https://cdn.hulaspark.com/models/%E6%B5%B7%E9%AD%94%E8%87%B3%E5%B0%8A_%E4%BA%9A%E6%89%98%E5%85%8B%E6%96%AF.glb', '海魔至尊主题亚托克斯模型', '20251022', 1, '2025-10-20 06:00:24', NULL, 1, 0, 1, NULL);
|
||||
INSERT INTO `sys_model` VALUES (4, 'victory_sona', '胜利女神_娑娜', 'https://cdn.hulaspark.com/models/%E8%83%9C%E5%88%A9%E5%A5%B3%E7%A5%9E_%E5%A8%91%E5%A8%9C.glb', '胜利女神主题娑娜模型', '20251022', 1, '2025-10-20 06:00:24', NULL, 1, 0, 1, NULL);
|
||||
INSERT INTO `sys_model` VALUES (5, 'ultimate_miss_fortune', '至臻_绝息圣堂_厄运小姐', 'https://cdn.hulaspark.com/models/%E8%87%B3%E8%87%BB_%E7%BB%9D%E6%81%AF%E5%9C%A3%E5%A0%82_%E5%8E%84%E8%BF%90%E5%B0%8F%E5%A7%90.glb', '至臻绝息圣堂主题厄运小姐模型', '20251022', 1, '2025-10-20 06:00:24', NULL, 1, 0, 1, NULL);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for undo_log
|
||||
-- ----------------------------
|
||||
@@ -2068,15 +2092,10 @@ CREATE TABLE `worker_node` (
|
||||
`created` timestamp NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`is_del` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 765 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'DB;WorkerID Assigner for UID Generator' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 845 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'DB;WorkerID Assigner for UID Generator' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of worker_node
|
||||
-- ----------------------------
|
||||
INSERT INTO `worker_node` VALUES (760, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153290834-59563', 2, '2025-10-11', '2025-10-11 11:28:11', '2025-10-11 11:28:11', 0);
|
||||
INSERT INTO `worker_node` VALUES (761, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153295768-6425', 2, '2025-10-11', '2025-10-11 11:28:16', '2025-10-11 11:28:16', 0);
|
||||
INSERT INTO `worker_node` VALUES (762, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153296437-43886', 2, '2025-10-11', '2025-10-11 11:28:16', '2025-10-11 11:28:16', 0);
|
||||
INSERT INTO `worker_node` VALUES (763, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153304108-67251', 2, '2025-10-11', '2025-10-11 11:28:24', '2025-10-11 11:28:24', 0);
|
||||
INSERT INTO `worker_node` VALUES (764, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153319987-85683', 2, '2025-10-11', '2025-10-11 11:28:40', '2025-10-11 11:28:40', 0);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -11,7 +11,7 @@
|
||||
Target Server Version : 80030 (8.0.30)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 11/10/2025 18:27:42
|
||||
Date: 20/10/2025 17:27:01
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@@ -412,7 +412,7 @@ CREATE TABLE `im_announcements` (
|
||||
`is_del` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82552736018433 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_as_ci COMMENT = '聊天公告表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 84990645864449 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_as_ci COMMENT = '聊天公告表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_announcements
|
||||
@@ -489,14 +489,14 @@ CREATE TABLE `im_contact` (
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE,
|
||||
INDEX `idx_contact_room_uid_hide`(`room_id` ASC, `uid` ASC, `hide` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 69082079229806 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会话列表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 69082079587433 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会话列表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_contact
|
||||
-- ----------------------------
|
||||
INSERT INTO `im_contact` VALUES (10937855681025, 10937855681024, 1, 0, 0, '2025-10-11 18:27:03.193', 1, 0, '2025-10-10 18:46:37.156', 82907955820032, '2025-03-27 04:23:08.420', '2025-10-11 18:27:03.194', 1, 0, 61170828519937, 0);
|
||||
INSERT INTO `im_contact` VALUES (10937855681025, 10937855681024, 1, 0, 0, '2025-10-11 11:38:14.092', 1, 0, '2025-10-10 18:46:37.156', 82907955820032, '2025-03-27 04:23:08.420', '2025-10-11 11:38:14.092', 1, 0, 61170828519937, 0);
|
||||
INSERT INTO `im_contact` VALUES (10937855681525, 1, 1, 0, 0, '2025-07-07 14:49:04.239', 1, 0, '2025-10-10 18:46:37.156', 82907955820032, '2025-03-27 04:23:08.420', '2025-10-10 10:46:38.197', 1, 0, NULL, 0);
|
||||
INSERT INTO `im_contact` VALUES (10937855681526, 10937855681024, 11229133317122, 0, 0, '2025-10-11 11:58:14.001', 1, 0, '2025-10-10 18:46:37.156', 82907955820032, '2025-03-27 04:23:08.420', '2025-10-11 11:58:14.001', 1, 0, 61170828519937, 0);
|
||||
INSERT INTO `im_contact` VALUES (10937855681526, 10937855681024, 11229133317122, 0, 0, '2025-10-11 11:38:15.691', 1, 0, '2025-10-10 18:46:37.156', 82907955820032, '2025-03-27 04:23:08.420', '2025-10-11 11:38:15.692', 1, 0, 61170828519937, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for im_feed
|
||||
@@ -579,7 +579,7 @@ CREATE TABLE `im_group_invite` (
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_invitee_state`(`invitee_uid` ASC, `state` ASC) USING BTREE,
|
||||
INDEX `idx_group`(`group_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 62581624628737 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '群组邀请记录表' ROW_FORMAT = DYNAMIC;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 62581624628737 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '群组邀请记录表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_group_invite
|
||||
@@ -609,7 +609,7 @@ CREATE TABLE `im_group_member` (
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE,
|
||||
INDEX `idx_group_member_uid_isdel_groupid`(`uid` ASC, `is_del` ASC, `group_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82522826436610 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '群成员表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86501702603272 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '群成员表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_group_member
|
||||
@@ -672,7 +672,7 @@ CREATE TABLE `im_message` (
|
||||
INDEX `idx_from_uid`(`from_uid` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82910984107521 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '消息表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86500645638657 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '消息表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_message
|
||||
@@ -702,7 +702,7 @@ CREATE TABLE `im_message_mark` (
|
||||
INDEX `idx_uid`(`uid` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82582746263553 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '消息标记表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86186840395265 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '消息标记表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_message_mark
|
||||
@@ -718,9 +718,9 @@ CREATE TABLE `im_notice` (
|
||||
`type` tinyint NOT NULL DEFAULT 1 COMMENT '通知类型 1群聊 2加好友',
|
||||
`sender_id` bigint NOT NULL COMMENT '发起人UID',
|
||||
`receiver_id` bigint NOT NULL COMMENT '接收人UID',
|
||||
`room_id` bigint NOT NULL COMMENT '房间ID',
|
||||
`apply_id` bigint NULL DEFAULT NULL COMMENT '申请ID',
|
||||
`operate_id` bigint NOT NULL COMMENT '房间ID',
|
||||
`name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '0' COMMENT '群昵称',
|
||||
`content` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '0' COMMENT '通知消息 [申请时填写]',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '处理状态:0-未处理;1-已同意;2-已拒绝',
|
||||
`is_read` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否已读',
|
||||
@@ -734,7 +734,7 @@ CREATE TABLE `im_notice` (
|
||||
INDEX `idx_receiver_type`(`receiver_id` ASC, `event_type` ASC) USING BTREE,
|
||||
INDEX `idx_sender`(`sender_id` ASC) USING BTREE,
|
||||
INDEX `idx_related`(`apply_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 83150193654275 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '统一通知表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86491313312259 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '统一通知表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_notice
|
||||
@@ -784,13 +784,12 @@ CREATE TABLE `im_room` (
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82522826436611 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '房间表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86501702603265 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '房间表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_room
|
||||
-- ----------------------------
|
||||
INSERT INTO `im_room` VALUES (1, 1, 1, '2025-10-10 18:46:37.156', 82907955820032, NULL, '2024-07-10 11:17:15.521', '2025-10-10 10:46:37.155', 1, 1, NULL, 0);
|
||||
INSERT INTO `im_room` VALUES (11229133317122, 2, 0, '2025-10-10 18:46:37.156', 82907955820032, NULL, '2024-07-10 11:17:15.521', '2025-10-11 03:35:25.988', 1, 1, NULL, 0);
|
||||
INSERT INTO `im_room` VALUES (1, 1, 1, '2025-10-20 16:42:41.743', 86500645638656, NULL, '2024-07-10 11:17:15.521', '2025-10-20 08:42:41.629', 1, 1, NULL, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for im_room_friend
|
||||
@@ -815,7 +814,7 @@ CREATE TABLE `im_room_friend` (
|
||||
INDEX `idx_room_id`(`room_id` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82522826436612 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '单聊房间表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86432953765380 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '单聊房间表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_room_friend
|
||||
@@ -844,7 +843,7 @@ CREATE TABLE `im_room_group` (
|
||||
INDEX `idx_room_id`(`room_id` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 74879168766467 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '群聊房间表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86501702603267 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '群聊房间表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_room_group
|
||||
@@ -901,7 +900,7 @@ CREATE TABLE `im_user` (
|
||||
`user_id` bigint NOT NULL DEFAULT 3 COMMENT 'def_user 的id',
|
||||
`user_type` tinyint NOT NULL DEFAULT 3 COMMENT '1: 系统用户,2:机器人,3:普通用户',
|
||||
`name` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户昵称',
|
||||
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户头像',
|
||||
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户头像',
|
||||
`email` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户邮箱',
|
||||
`account` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户账号',
|
||||
`sex` int NULL DEFAULT NULL COMMENT '性别 1为男性,2为女性',
|
||||
@@ -927,13 +926,13 @@ CREATE TABLE `im_user` (
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE,
|
||||
INDEX `idx_active_status_last_opt_time`(`last_opt_time` ASC) USING BTREE,
|
||||
INDEX `account_UNIQUE`(`account` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82522826436609 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86432953765377 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `im_user` VALUES (1, 61170828519936, 2, 'HuLa小管家', '022', '', 'bot', NULL, '', 17, '2025-07-07 15:27:01.711', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"120.231.232.41\", \"createIpDetail\": {\"ip\": \"206.237.119.215\", \"isp\": \"\", \"area\": \"\", \"city\": \"\", \"isp_id\": \"\", \"region\": \"\", \"city_id\": \"\", \"country\": \"美国\", \"region_id\": \"\", \"country_id\": \"US\"}, \"updateIpDetail\": {\"ip\": \"120.231.232.41\", \"isp\": \"移动\", \"area\": \"\", \"city\": \"\", \"isp_id\": \"100025\", \"region\": \"广东\", \"city_id\": \"\", \"country\": \"中国\", \"region_id\": \"440000\", \"country_id\": \"CN\"}}', 6, 0, '', '2025-03-27 04:23:08.393', '2025-09-17 02:34:06.481', 'k.23772439646234', 0, NULL, 0, '2025-05-09 18:24:37.089', 99978, 0, 1);
|
||||
INSERT INTO `im_user` VALUES (10937855681024, 61170828519937, 3, 'Dawn', 'https://cdn.hulaspark.com/avatar/2439646234/97320189485dca88dcc7a70054445a56.webp', '2439646234@qq.com', '2439646234', NULL, '', 4, '2025-07-30 15:31:57.651', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"192.168.1.37\", \"createIpDetail\": null, \"updateIpDetail\": {\"ip\": \"192.168.1.37\", \"isp\": \"内网IP\", \"area\": \"\", \"city\": \"内网IP\", \"isp_id\": \"local\", \"region\": \"\", \"city_id\": \"local\", \"country\": \"\", \"region_id\": \"\", \"country_id\": \"\"}}', 6, 0, '', '2025-03-27 04:23:08.393', '2025-10-11 10:27:11.457', 'k.2439646234', 0, NULL, 0, '2025-09-20 21:35:31.415', 99978, 0, 1);
|
||||
INSERT INTO `im_user` VALUES (1, 61170828519936, 2, 'HuLa小管家', '022', '', 'bot', NULL, '', 0, '2025-07-07 15:27:01.711', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"120.231.232.41\", \"createIpDetail\": {\"ip\": \"206.237.119.215\", \"isp\": \"\", \"area\": \"\", \"city\": \"\", \"isp_id\": \"\", \"region\": \"\", \"city_id\": \"\", \"country\": \"美国\", \"region_id\": \"\", \"country_id\": \"US\"}, \"updateIpDetail\": {\"ip\": \"120.231.232.41\", \"isp\": \"移动\", \"area\": \"\", \"city\": \"\", \"isp_id\": \"100025\", \"region\": \"广东\", \"city_id\": \"\", \"country\": \"中国\", \"region_id\": \"440000\", \"country_id\": \"CN\"}}', 6, 0, '', '2025-03-27 04:23:08.393', '2025-10-11 10:14:24.150', 'k.23772439646234', 0, NULL, 0, '2025-05-09 18:24:37.089', 99978, 0, 1);
|
||||
INSERT INTO `im_user` VALUES (10937855681024, 61170828519937, 3, 'Dawn', 'https://cdn.hulaspark.com/avatar/2439646234/97320189485dca88dcc7a70054445a56.webp', '2439646234@qq.com', '2439646234', NULL, '', 26, '2025-07-30 15:31:57.651', '{\"createIp\": \"206.237.119.215\", \"updateIp\": \"192.168.1.26\", \"createIpDetail\": null, \"updateIpDetail\": {\"ip\": \"192.168.1.26\", \"isp\": \"内网IP\", \"area\": \"\", \"city\": \"内网IP\", \"isp_id\": \"local\", \"region\": \"\", \"city_id\": \"local\", \"country\": \"\", \"region_id\": \"\", \"country_id\": \"\"}}', 6, 0, '', '2025-03-27 04:23:08.393', '2025-10-20 14:27:30.170', 'k.2439646234', 0, NULL, 0, '2025-09-20 21:35:31.415', 99978, 0, 1);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for im_user_apply
|
||||
@@ -962,7 +961,7 @@ CREATE TABLE `im_user_apply` (
|
||||
INDEX `idx_target_id`(`target_id` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82880386659841 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户申请表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86491313312257 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户申请表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_user_apply
|
||||
@@ -989,7 +988,7 @@ CREATE TABLE `im_user_backpack` (
|
||||
INDEX `idx_uid`(`uid` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82522826436619 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户背包表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86432953765387 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户背包表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_user_backpack
|
||||
@@ -1032,7 +1031,7 @@ CREATE TABLE `im_user_emoji` (
|
||||
`update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `IDX_USER_EMOJIS_UID`(`uid` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 80580641386497 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户表情包' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 85336302651905 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户表情包' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_user_emoji
|
||||
@@ -1065,7 +1064,7 @@ CREATE TABLE `im_user_friend` (
|
||||
INDEX `idx_uid_friend_uid`(`uid` ASC, `friend_uid` ASC) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE,
|
||||
INDEX `idx_update_time`(`update_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82881355544066 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户联系人表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86489446846978 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户联系人表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of im_user_friend
|
||||
@@ -1243,7 +1242,7 @@ CREATE TABLE `secure_invoke_record` (
|
||||
`is_del` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_next_retry_time`(`next_retry_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 82910984107522 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '本地消息表' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 86500645638658 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '本地消息表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of secure_invoke_record
|
||||
@@ -1262,12 +1261,10 @@ CREATE TABLE `worker_node` (
|
||||
`modified` timestamp NULL DEFAULT NULL COMMENT '修改时间',
|
||||
`created` timestamp NULL DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 192 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'DB;WorkerID Assigner for UID Generator' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 202 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'DB;WorkerID Assigner for UID Generator' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of worker_node
|
||||
-- ----------------------------
|
||||
INSERT INTO `worker_node` VALUES (190, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153294125-92616', 2, '2025-10-11', '2025-10-11 11:28:14', '2025-10-11 11:28:14');
|
||||
INSERT INTO `worker_node` VALUES (191, '240e:3b3:30b4:1f60:d382:ae04:eb18:d48', '1760153797714-77047', 2, '2025-10-11', '2025-10-11 11:36:38', '2025-10-11 11:36:38');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
上传目录下的docker文件夹到服务器/home/docker下面, 需要修改env文件夹rocketmq文件夹里面的配置, 特别是[broker.conf](docker/rocketmq/broker/conf/broker.conf)里面brokerIP1的值
|
||||
|
||||
## 🛠️ 注册时需要的邮箱功能
|
||||
- **配置邮箱密钥**: 
|
||||
|
||||
## 🛠️ 启动命令
|
||||
- **提高权限**: sudo chmod -R 777 /home/docker/rocketmq
|
||||
|
||||
Binary file not shown.
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>luohuo-ai-controller</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>luohuo-ai-entity</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-ai</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>luohuo-ai-facade</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-ai</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../luohuo-dependencies-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-base</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ import java.util.Collection;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
|
||||
public class DefDictItemServiceImpl extends SuperServiceImpl<DefDictManager, Long, DefDict> implements DefDictItemService {
|
||||
|
||||
private final CachePlusOps cachePlusOps;
|
||||
|
||||
@@ -216,15 +216,16 @@ public class DefUserServiceImpl extends SuperCacheServiceImpl<DefUserManager, Lo
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updatePassword(DefUserPasswordUpdateVO data) {
|
||||
// ArgumentAssert.notEmpty(data.getOldPassword(), "请输入旧密码");
|
||||
ArgumentAssert.notEmpty(data.getOldPassword(), "请输入旧密码");
|
||||
DefUser user = superManager.getUserByEmail(2, data.getEmail());
|
||||
ArgumentAssert.notNull(user, "用户不存在");
|
||||
// ArgumentAssert.equals(user.getId(), ContextUtil.getUid(), "只能修改自己的密码");
|
||||
ArgumentAssert.equals(user.getId(), ContextUtil.getUid(), "只能修改自己的密码");
|
||||
// String oldPassword = SecureUtil.sha256(data.getOldPassword() + user.getSalt());
|
||||
// ArgumentAssert.equals(user.getPassword(), oldPassword, "旧密码错误");
|
||||
CacheKey cacheKey = new CaptchaCacheKeyBuilder().key(data.getEmail(), data.getKey());
|
||||
CacheResult<String> code = cacheOps.get(cacheKey);
|
||||
ArgumentAssert.equals(code.getValue(), data.getCode(), "验证码不正确");
|
||||
cacheOps.del(cacheKey);
|
||||
|
||||
return updateUserPassword(user.getId(), data.getPassword(), user.getSalt());
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-base</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-base</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-base-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-base-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-base-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-base</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-base</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../luohuo-dependencies-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.basic</groupId>
|
||||
<artifactId>luohuo-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -21,8 +21,8 @@
|
||||
<description>luohuo项目业务父pom</description>
|
||||
<url>https://gitee.com/HuLaSpark/HuLa-Server</url>
|
||||
<properties>
|
||||
<luohuo-util.version>2.6.15</luohuo-util.version>
|
||||
<luohuo-project.version>2.6.15</luohuo-project.version>
|
||||
<luohuo-util.version>3.0.0</luohuo-util.version>
|
||||
<luohuo-project.version>3.0.0</luohuo-project.version>
|
||||
<docker.image.prefix>hula</docker.image.prefix>
|
||||
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
||||
</properties>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-gateway</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-gateway</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../luohuo-dependencies-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-generator</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class ProjectUtilsTest {
|
||||
vo.setParent("com.luohuo.flex");
|
||||
vo.setGroupId("com.luohuo.flex");
|
||||
vo.setUtilParent("com.luohuo.basic");
|
||||
vo.setVersion("2.6.15");
|
||||
vo.setVersion("3.0.0");
|
||||
vo.setDescription("测试服务");
|
||||
vo.setServerPort(8080);
|
||||
ProjectUtils.generator(vo, new DatabaseProperties());
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-generator</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-generator</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-generator</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../luohuo-dependencies-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-im</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -129,12 +129,6 @@
|
||||
<artifactId>luohuo-im-cloud-impl</artifactId>
|
||||
<version>${luohuo-project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-presence-cloud-impl</artifactId>
|
||||
<version>${luohuo-project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.luohuo.flex.im.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* 幂等类型 TODO 需要删除
|
||||
* @author nyh
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum LoginTypeEnum {
|
||||
PC("pc", "PC端"),
|
||||
MOBILE("mobile", "移动端"),
|
||||
;
|
||||
|
||||
private final String type;
|
||||
private final String desc;
|
||||
|
||||
public static LoginTypeEnum match(String val, LoginTypeEnum def) {
|
||||
return Stream.of(values()).parallel().filter((item) -> item.getType().equals(val)).findAny().orElse(def);
|
||||
}
|
||||
|
||||
public static LoginTypeEnum get(String val) {
|
||||
return match(val, null);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.luohuo.flex.im.common.event.listener;
|
||||
|
||||
import com.luohuo.flex.im.api.PresenceApi;
|
||||
import com.luohuo.flex.common.OnlineService;
|
||||
import com.luohuo.flex.im.common.event.GroupMemberAddEvent;
|
||||
import com.luohuo.flex.im.core.chat.dao.GroupMemberDao;
|
||||
import com.luohuo.flex.im.core.chat.service.adapter.MemberAdapter;
|
||||
@@ -33,7 +33,7 @@ public class GroupMemberAddListener {
|
||||
private UserCache userCache;
|
||||
private GroupMemberDao groupMemberDao;
|
||||
private GroupMemberCache groupMemberCache;
|
||||
private PresenceApi presenceApi;
|
||||
private OnlineService onlineService;
|
||||
private PushService pushService;
|
||||
|
||||
/**
|
||||
@@ -47,7 +47,7 @@ public class GroupMemberAddListener {
|
||||
Long roomId = event.getRoomId();
|
||||
List<Long> memberUidList = groupMemberCache.getMemberExceptUidList(roomId);
|
||||
// 在线的用户
|
||||
List<Long> onlineUids = presenceApi.getGroupOnlineMembers(roomId).getData();
|
||||
List<Long> onlineUids = onlineService.getGroupOnlineMembers(roomId);
|
||||
Map<Long, User> map = userCache.getBatch(event.getMemberList());
|
||||
|
||||
List<ChatMember> memberResps = groupMemberDao.getMemberListByUid(event.getMemberList());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.luohuo.flex.im.common.event.listener;
|
||||
|
||||
import com.luohuo.flex.im.core.user.service.cache.ItemCache;
|
||||
import com.luohuo.flex.im.core.user.service.cache.UserCache;
|
||||
import com.luohuo.flex.im.core.user.service.cache.UserSummaryCache;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -30,6 +31,8 @@ public class ItemReceiveListener {
|
||||
private UserDao userDao;
|
||||
@Resource
|
||||
private ItemCache itemCache;
|
||||
@Resource
|
||||
private UserCache userCache;
|
||||
@Resource
|
||||
private UserSummaryCache userSummaryCache;
|
||||
|
||||
@@ -47,6 +50,7 @@ public class ItemReceiveListener {
|
||||
User user = userDao.getById(userBackpack.getUid());
|
||||
if (Objects.isNull(user.getItemId())) {
|
||||
userDao.wearingBadge(userBackpack.getUid(), userBackpack.getItemId());
|
||||
userCache.delete(userBackpack.getUid());
|
||||
userSummaryCache.delete(userBackpack.getUid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ public class MessageRecallListener {
|
||||
@TransactionalEventListener(classes = MessageRecallEvent.class, fallbackExecution = true)
|
||||
public void evictMsg(MessageRecallEvent event) {
|
||||
ChatMsgRecallDTO recallDTO = event.getRecallDTO();
|
||||
// msgCache.evictMsg(recallDTO.getMsgId());
|
||||
msgCache.delete(recallDTO.getMsgId());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.luohuo.flex.im.core.chat.consumer;
|
||||
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.flex.common.cache.PassageMsgCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.constant.MqConstant;
|
||||
import com.luohuo.flex.im.core.chat.dao.ContactDao;
|
||||
import com.luohuo.flex.im.core.chat.service.cache.MsgCache;
|
||||
import com.luohuo.flex.im.domain.entity.Message;
|
||||
import com.luohuo.flex.model.ws.AckMessageDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.MessageModel;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 目前架构ws服务无法处理业务,客户端回执给ws服务之后进行mq跳转至此
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Slf4j
|
||||
@RocketMQMessageListener(consumerGroup = MqConstant.MSG_PUSH_ACK_TOPIC_GROUP, topic = MqConstant.MSG_PUSH_ACK_TOPIC, messageModel = MessageModel.CLUSTERING)
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class AckConsumer implements RocketMQListener<AckMessageDTO> {
|
||||
|
||||
private MsgCache msgCache;
|
||||
private ContactDao contactDao;
|
||||
private CachePlusOps cachePlusOps;
|
||||
|
||||
/**
|
||||
* 通过mq的方式 回调进行回执
|
||||
* @param dto
|
||||
*/
|
||||
@Override
|
||||
public void onMessage(AckMessageDTO dto) {
|
||||
Message message = msgCache.get(dto.getMsgId());
|
||||
if(message == null){
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 更新收到消息的状态
|
||||
contactDao.refreshOrCreateActiveTime(message.getRoomId(), Arrays.asList(dto.getUid()), message.getId(), message.getCreateTime());
|
||||
|
||||
// 2. 删除在途消息
|
||||
cachePlusOps.sRem(PassageMsgCacheKeyBuilder.build(dto.getUid()), message.getId());
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.luohuo.flex.im.core.chat.consumer;
|
||||
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.basic.context.ContextUtil;
|
||||
import com.luohuo.flex.common.OnlineService;
|
||||
import com.luohuo.flex.common.cache.PassageMsgCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.constant.MqConstant;
|
||||
import com.luohuo.flex.im.core.chat.dao.ContactDao;
|
||||
import com.luohuo.flex.im.core.chat.dao.MessageDao;
|
||||
import com.luohuo.flex.im.core.chat.dao.RoomDao;
|
||||
import com.luohuo.flex.im.core.chat.dao.RoomFriendDao;
|
||||
@@ -27,15 +29,18 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.MessageModel;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 发送消息更新房间收信箱,并同步给房间成员信箱
|
||||
* 加入 在途消息缓存,三秒没有回执则再次推送
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Slf4j
|
||||
@@ -50,8 +55,9 @@ public class MsgSendConsumer implements RocketMQListener<MsgSendMessageDTO> {
|
||||
private RoomDao roomDao;
|
||||
private GroupMemberCache groupMemberCache;
|
||||
private RoomFriendDao roomFriendDao;
|
||||
private ContactDao contactDao;
|
||||
private OnlineService onlineService;
|
||||
private PushService pushService;
|
||||
private CachePlusOps cachePlusOps;
|
||||
|
||||
@Override
|
||||
public void onMessage(MsgSendMessageDTO dto) {
|
||||
@@ -74,8 +80,8 @@ public class MsgSendConsumer implements RocketMQListener<MsgSendMessageDTO> {
|
||||
memberUidList.add(roomFriend.getUid2());
|
||||
}
|
||||
|
||||
// 2. 更新所有群成员的会话时间, 并推送房间成员
|
||||
contactDao.refreshOrCreateActiveTime(room.getId(), memberUidList, message.getId(), message.getCreateTime());
|
||||
// 2. 过滤出在线的人员
|
||||
Set<Long> onlineUsersList = onlineService.getOnlineUsersList(memberUidList);
|
||||
|
||||
// 3. 与在线人员交集并进行路由
|
||||
switch (MessageTypeEnum.of(message.getType())) {
|
||||
@@ -85,6 +91,7 @@ public class MsgSendConsumer implements RocketMQListener<MsgSendMessageDTO> {
|
||||
// 3.1 给自己推送原始消息
|
||||
WsBaseResp<ChatMessageResp> selfResp = WsAdapter.buildMsgSend(chatService.getMsgResp(message, null));
|
||||
pushService.sendPushMsg(selfResp, uid, dto.getUid());
|
||||
asyncSavePassageMsg(message.getId(), selfResp, Set.of(uid), dto.getUid());
|
||||
|
||||
// 3.2 修改消息发送者为通话创建者(用于其他人接收)
|
||||
Long originalFromUid = message.getFromUid();
|
||||
@@ -101,20 +108,42 @@ public class MsgSendConsumer implements RocketMQListener<MsgSendMessageDTO> {
|
||||
message.setFromUid(creator);
|
||||
|
||||
// 3.3 推送给其他成员
|
||||
List<Long> otherMembers = new ArrayList<>(memberUidList);
|
||||
otherMembers.remove(uid);
|
||||
onlineUsersList.remove(uid);
|
||||
List<Long> otherMembers = new ArrayList<>(onlineUsersList);
|
||||
|
||||
WsBaseResp<ChatMessageResp> othersResp = WsAdapter.buildMsgSend(chatService.getMsgResp(message, null));
|
||||
// 恢复原始发送者显示
|
||||
othersResp.getData().getFromUser().setUid(originalFromUid + "");
|
||||
pushService.sendPushMsg(othersResp, otherMembers, dto.getUid());
|
||||
asyncSavePassageMsg(message.getId(), othersResp, onlineUsersList, dto.getUid());
|
||||
message.setFromUid(originalFromUid);
|
||||
}
|
||||
default -> {
|
||||
// 常规消息处理
|
||||
WsBaseResp<ChatMessageResp> wsBaseResp = WsAdapter.buildMsgSend(chatService.getMsgResp(message, null));
|
||||
pushService.sendPushMsg(wsBaseResp, memberUidList, dto.getUid());
|
||||
pushService.sendPushMsg(wsBaseResp, new ArrayList<>(onlineUsersList), dto.getUid());
|
||||
asyncSavePassageMsg(message.getId(), wsBaseResp, onlineUsersList, dto.getUid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里理论上一定会比 pushService 到达前端后在ack给后端 先执行完成
|
||||
* @param messageId 消息的id [唯一标识,未来升级为hash之后的值]
|
||||
* @param wsBaseResp 推送的消息
|
||||
* @param memberUidList 推送的列表
|
||||
* @param cuid 操作人
|
||||
*/
|
||||
@Async
|
||||
public void asyncSavePassageMsg(Long messageId, WsBaseResp<?> wsBaseResp, Set<Long> memberUidList, Long cuid) {
|
||||
// 1. 发送重试消息
|
||||
pushService.sendPushMsgWithRetry(wsBaseResp, new ArrayList<>(memberUidList), messageId, cuid);
|
||||
|
||||
// 2. 给每条消息加入 在途的状态
|
||||
memberUidList.forEach(memberUid -> {
|
||||
// 添加在途消息
|
||||
cachePlusOps.sAdd(PassageMsgCacheKeyBuilder.build(memberUid), messageId);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.luohuo.flex.im.core.chat.consumer;
|
||||
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.flex.common.cache.PassageMsgCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.constant.MqConstant;
|
||||
import com.luohuo.flex.im.core.chat.dao.ContactDao;
|
||||
import com.luohuo.flex.im.core.user.service.impl.PushService;
|
||||
import com.luohuo.flex.model.entity.dto.NodePushDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.MessageModel;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 消息推送延迟二次推送专属消费者 [系统自己发起]
|
||||
* 收到重试消息之后判断路由的uid是否传递的消息是否还在途中,再途的话再次发送
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Slf4j
|
||||
@RocketMQMessageListener(
|
||||
topic = MqConstant.PUSH_DELAY_TOPIC,
|
||||
consumerGroup = MqConstant.PUSH_DELAY_GROUP,
|
||||
messageModel = MessageModel.CLUSTERING,
|
||||
maxReconsumeTimes = 3
|
||||
)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RetryPushConsumer implements RocketMQListener<NodePushDTO> {
|
||||
private final CachePlusOps cachePlusOps;
|
||||
private final PushService pushService;
|
||||
private final ContactDao contactDao;
|
||||
|
||||
@Override
|
||||
public void onMessage(NodePushDTO message) {
|
||||
Map<String, Long> deviceUserMap = message.getDeviceUserMap();
|
||||
deviceUserMap.values().forEach(uid -> {
|
||||
Boolean exist = cachePlusOps.sIsMember(PassageMsgCacheKeyBuilder.build(uid), message.getHashId());
|
||||
|
||||
if (exist) {
|
||||
log.info("ack失败重新发送消息: {}", message);
|
||||
pushService.sendPushMsg(message.getWsBaseMsg(), Arrays.asList(uid), message.getUid());
|
||||
|
||||
// 直接更新会话的最后一条消息的id
|
||||
LinkedHashMap<String, Object> dataMap = (LinkedHashMap<String, Object>) message.getWsBaseMsg().getData();
|
||||
LinkedHashMap<String, Object> msg = (LinkedHashMap<String, Object>) dataMap.get("message");
|
||||
LinkedHashMap<String, Object> user = (LinkedHashMap<String, Object>) dataMap.get("fromUser");
|
||||
contactDao.refreshOrCreateActive(msg.get("roomId"), Arrays.asList(Long.parseLong(user.get("uid").toString())), msg.get("id"), msg.get("sendTime"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,14 @@ public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
||||
.one();
|
||||
}
|
||||
|
||||
public Integer getReadCount(Message message) {
|
||||
public List<Contact> get(Long uid, List<Long> roomIdList) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getUid, uid)
|
||||
.in(Contact::getRoomId, roomIdList)
|
||||
.list();
|
||||
}
|
||||
|
||||
public Integer getReadCount(Message message) {
|
||||
return Math.toIntExact(lambdaQuery()
|
||||
.eq(Contact::getHide, false)
|
||||
.eq(Contact::getRoomId, message.getRoomId())
|
||||
@@ -96,6 +103,11 @@ public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
||||
baseMapper.refreshOrCreateActiveTime(roomId, memberUidList, msgId, activeTime);
|
||||
}
|
||||
|
||||
@TenantIgnore
|
||||
public void refreshOrCreateActive(Object roomId, List<Long> memberUidList, Object msgId, Object activeTime) {
|
||||
baseMapper.refreshOrCreateActive(roomId, memberUidList, msgId, activeTime);
|
||||
}
|
||||
|
||||
public void refreshOrCreate(Long roomId, Long uid) {
|
||||
baseMapper.refreshOrCreate(roomId, uid);
|
||||
}
|
||||
|
||||
@@ -82,15 +82,6 @@ public class MessageDao extends ServiceImpl<MessageMapper, Message> {
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@TenantIgnore
|
||||
public Integer getUnReadCount(Long roomId, LocalDateTime readTime, Long uid) {
|
||||
return Math.toIntExact(lambdaQuery()
|
||||
.eq(Message::getRoomId, roomId)
|
||||
.gt(Objects.nonNull(readTime), Message::getCreateTime, readTime)
|
||||
.ne(Message::getFromUid, uid)
|
||||
.count());
|
||||
}
|
||||
|
||||
public Map<Long, Integer> batchGetUnReadCount(Collection<Contact> contactList) {
|
||||
return baseMapper.batchGetUnReadCount(contactList);
|
||||
}
|
||||
|
||||
@@ -20,5 +20,15 @@ public interface ContactMapper extends BaseMapper<Contact> {
|
||||
|
||||
void refreshOrCreateActiveTime(@Param("roomId") Long roomId, @Param("memberUidList") List<Long> memberUidList, @Param("msgId") Long msgId, @Param("activeTime") LocalDateTime activeTime);
|
||||
|
||||
/**
|
||||
* 刷新会话状态,ack专用
|
||||
*/
|
||||
void refreshOrCreateActive(@Param("roomId") Object roomId, @Param("memberUidList") List<Long> memberUidList, @Param("msgId") Object msgId, @Param("activeTime") Object activeTime);
|
||||
|
||||
/**
|
||||
* 刷新或创建会话
|
||||
* @param roomId 房间id
|
||||
* @param uid 用户id
|
||||
*/
|
||||
void refreshOrCreate(@Param("roomId") Long roomId, @Param("uid") Long uid);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ public class ChatServiceImpl implements ChatService {
|
||||
private ContactDao contactDao;
|
||||
private RoomCache roomCache;
|
||||
private GroupMemberDao groupMemberDao;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
@@ -188,6 +187,47 @@ public class ChatServiceImpl implements ChatService {
|
||||
return Stream.concat(groupRoomIds.stream(), friendRoomIds.stream()).distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会话的最后一条消息ID
|
||||
*/
|
||||
@Async
|
||||
public void updateContactLastMsgIds(Long receiveUid, Map<Long, List<Message>> groupedMessages) {
|
||||
// 获取每个房间的最大消息ID
|
||||
Map<Long, Long> roomMaxMsgIds = new HashMap<>();
|
||||
for (Map.Entry<Long, List<Message>> entry : groupedMessages.entrySet()) {
|
||||
Long roomId = entry.getKey();
|
||||
List<Message> roomMessages = entry.getValue();
|
||||
|
||||
if (CollUtil.isNotEmpty(roomMessages)) {
|
||||
// 找到房间中最大的消息ID
|
||||
Long maxMsgId = roomMessages.stream()
|
||||
.map(Message::getId)
|
||||
.max(Long::compareTo)
|
||||
.orElse(null);
|
||||
|
||||
if (maxMsgId != null) {
|
||||
roomMaxMsgIds.put(roomId, maxMsgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量更新会话的最后一条消息ID
|
||||
if (!roomMaxMsgIds.isEmpty()) {
|
||||
List<Long> roomIds = new ArrayList<>(roomMaxMsgIds.keySet());
|
||||
List<Contact> contacts = contactDao.get(receiveUid, roomIds);
|
||||
|
||||
for (Contact contact : contacts) {
|
||||
Long maxMsgId = roomMaxMsgIds.get(contact.getRoomId());
|
||||
if (maxMsgId != null && (contact.getLastMsgId() == null || maxMsgId > contact.getLastMsgId())) {
|
||||
contact.setLastMsgId(maxMsgId);
|
||||
}
|
||||
}
|
||||
|
||||
contactDao.updateBatchById(contacts);
|
||||
log.info("已更新{}个会话的最后消息ID", contacts.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChatMessageResp> getMsgList(MsgReq msgReq, Long receiveUid) {
|
||||
List<Message> messages;
|
||||
@@ -198,21 +238,40 @@ public class ChatServiceImpl implements ChatService {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 2. 计算查询的时间范围(最多15天)
|
||||
LocalDateTime effectiveStartTime = calculateStartTime(msgReq.getLastOptTime());
|
||||
messages = messageDao.list(new LambdaQueryWrapper<Message>().in(Message::getRoomId, roomIds)
|
||||
.between(Message::getCreateTime, effectiveStartTime, LocalDateTime.now()));
|
||||
// 2. 如果开启同步功能,那么把最近N天的消息拉回去, 否则获取所有未ack的消息 [要排除屏蔽的房间的消息]
|
||||
if(msgReq.getAsync()){
|
||||
LocalDateTime effectiveStartTime = calculateStartTime(TimeUtils.getTime(LocalDateTime.now().minusDays(14)));
|
||||
messages = messageDao.list(new LambdaQueryWrapper<Message>().in(Message::getRoomId, roomIds)
|
||||
.between(Message::getCreateTime, effectiveStartTime, LocalDateTime.now()));
|
||||
} else {
|
||||
// 3. 获取到需要拉取的消息的会话,根据会话拿到最后一个ack的消息id TODO 需要走缓存
|
||||
List<Contact> contacts = contactDao.get(receiveUid, roomIds);
|
||||
|
||||
// 查询每个房间中消息id 之后的所有消息
|
||||
LambdaQueryWrapper<Message> batchWrapper = new LambdaQueryWrapper<>();
|
||||
for (Contact contact : contacts) {
|
||||
Long lastMsgId = contact.getLastMsgId() != null ? contact.getLastMsgId() : 0;
|
||||
batchWrapper.or(w -> w.eq(Message::getRoomId, contact.getRoomId()).ge(Message::getId, lastMsgId));
|
||||
}
|
||||
batchWrapper.orderByAsc(Message::getId);
|
||||
messages = messageDao.list(batchWrapper);
|
||||
}
|
||||
} else {
|
||||
messages = getMsgByIds(msgReq.getMsgIds());
|
||||
}
|
||||
|
||||
Map<Long, List<Message>> groupedMessages = messages.stream().collect(Collectors.groupingBy(Message::getRoomId));
|
||||
|
||||
// 3. 转换为响应对象并返回
|
||||
// 5. 转换为响应对象并返回
|
||||
List<ChatMessageResp> baseMessages = new ArrayList<>();
|
||||
for (Long roomId : groupedMessages.keySet()) {
|
||||
baseMessages.addAll(getMsgRespBatch(groupedMessages.get(roomId), receiveUid));
|
||||
}
|
||||
|
||||
// 6. 更新会话的最后一条消息ID [不是查询消息、不是同步数据; 只有是登录获取会话id差额数据的时候才更新会话最后的id]
|
||||
if (CollUtil.isEmpty(msgReq.getMsgIds()) && !msgReq.getAsync()) {
|
||||
updateContactLastMsgIds(receiveUid, groupedMessages);
|
||||
}
|
||||
return baseMessages;
|
||||
}
|
||||
|
||||
@@ -267,7 +326,7 @@ public class ChatServiceImpl implements ChatService {
|
||||
public void recallMsg(Long uid, ChatMessageBaseReq request) {
|
||||
Message message = messageDao.getById(request.getMsgId());
|
||||
//校验能不能执行撤回
|
||||
Integer roleId = checkRecall(uid, message);
|
||||
checkRecall(uid, message);
|
||||
recallMsgHandler.recall(uid, getRoomHowPeople(uid, message.getRoomId()), message);
|
||||
}
|
||||
|
||||
@@ -345,19 +404,22 @@ public class ChatServiceImpl implements ChatService {
|
||||
/**
|
||||
* @return 返回撤回人的权限
|
||||
*/
|
||||
private Integer checkRecall(Long uid, Message message) {
|
||||
private void checkRecall(Long uid, Message message) {
|
||||
AssertUtil.isNotEmpty(message, "消息有误");
|
||||
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL.getType(), "消息无法撤回");
|
||||
|
||||
GroupMember member = groupMemberCache.getMemberDetail(message.getRoomId(), uid);
|
||||
if (member.getRoleId().equals(GroupRoleEnum.LEADER.getType()) || member.getRoleId().equals(GroupRoleEnum.MANAGER.getType())) {
|
||||
return member.getRoleId();
|
||||
}
|
||||
Room room = roomCache.get(message.getRoomId());
|
||||
if(room.getType().equals(RoomTypeEnum.GROUP.getType())){
|
||||
GroupMember member = groupMemberCache.getMemberDetail(message.getRoomId(), uid);
|
||||
if (member.getRoleId().equals(GroupRoleEnum.LEADER.getType()) || member.getRoleId().equals(GroupRoleEnum.MANAGER.getType())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean self = Objects.equals(uid, message.getFromUid());
|
||||
AssertUtil.isTrue(self, "抱歉,您没有权限");
|
||||
long between = Duration.between(message.getCreateTime(), LocalDateTime.now()).toMinutes();
|
||||
AssertUtil.isTrue(between < 2, "超过2分钟的消息不能撤回");
|
||||
return member.getRoleId();
|
||||
}
|
||||
|
||||
public List<ChatMessageResp> getMsgRespBatch(List<Message> messages, Long receiveUid) {
|
||||
|
||||
@@ -12,8 +12,9 @@ import com.luohuo.basic.exception.code.ResponseEnum;
|
||||
import com.luohuo.basic.model.cache.CacheKey;
|
||||
import com.luohuo.basic.utils.SpringUtils;
|
||||
import com.luohuo.basic.utils.TimeUtils;
|
||||
import com.luohuo.flex.common.OnlineService;
|
||||
import com.luohuo.flex.common.cache.PresenceCacheKeyBuilder;
|
||||
import com.luohuo.flex.im.api.PresenceApi;
|
||||
import com.luohuo.flex.common.constant.DefValConstants;
|
||||
import com.luohuo.flex.im.core.chat.dao.RoomFriendDao;
|
||||
import com.luohuo.flex.im.core.chat.dao.RoomGroupDao;
|
||||
import com.luohuo.flex.im.core.user.dao.NoticeDao;
|
||||
@@ -142,7 +143,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
private GroupMemberCache groupMemberCache;
|
||||
private PushService pushService;
|
||||
private FriendService friendService;
|
||||
private PresenceApi presenceApi;
|
||||
private OnlineService onlineService;
|
||||
private TransactionTemplate transactionTemplate;
|
||||
|
||||
private void warmUpGroupMemberCache(Long roomId) {
|
||||
@@ -279,7 +280,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
Set<Long> groupIdList = voList.stream().map(MemberResp::getGroupId).collect(Collectors.toSet());
|
||||
List<Long> roomIdList = voList.stream().map(MemberResp::getRoomId).collect(Collectors.toList());
|
||||
|
||||
Map<Long, Long> onlineMap = presenceApi.getBatchGroupOnlineCounts(roomIdList).getData();
|
||||
Map<Long, Long> onlineMap = onlineService.getBatchGroupOnlineCounts(roomIdList);
|
||||
List<GroupMember> members = groupMemberDao.getGroupMemberByGroupIdListAndUid(uid, groupIdList);
|
||||
Map<Long, GroupMember> map = members.stream().collect(Collectors.toMap(GroupMember::getGroupId, Function.identity()));
|
||||
|
||||
@@ -331,10 +332,10 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
groupMemberDao.addAdmin(roomGroup.getId(), request.getUidList());
|
||||
|
||||
// 每个被邀请的人都要收到邀请进群的消息
|
||||
setAdminNotice(NoticeTypeEnum.GROUP_SET_ADMIN, uid, request.getUidList(), manageUidList, roomGroup.getName());
|
||||
setAdminNotice(NoticeTypeEnum.GROUP_SET_ADMIN, uid, request.getUidList(), manageUidList, roomGroup.getRoomId());
|
||||
}
|
||||
|
||||
private void setAdminNotice(NoticeTypeEnum noticeTypeEnum, Long uid, List<Long> uidList, List<Long> manageUidList, String content) {
|
||||
private void setAdminNotice(NoticeTypeEnum noticeTypeEnum, Long uid, List<Long> uidList, List<Long> manageUidList, Long roomId) {
|
||||
long uuid = uidGenerator.getUid();
|
||||
uidList.stream().filter(id -> !manageUidList.contains(id)).forEach(id -> {
|
||||
// 通知被操作的人
|
||||
@@ -345,7 +346,8 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
id,
|
||||
uuid,
|
||||
id,
|
||||
content
|
||||
roomId,
|
||||
""
|
||||
);
|
||||
|
||||
// 通知群主
|
||||
@@ -356,7 +358,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
// uid,
|
||||
// uuid,
|
||||
// id,
|
||||
// content
|
||||
// roomId
|
||||
// );
|
||||
});
|
||||
}
|
||||
@@ -385,7 +387,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
|
||||
// 4. 撤销管理员
|
||||
groupMemberDao.revokeAdmin(roomGroup.getId(), request.getUidList());
|
||||
setAdminNotice(NoticeTypeEnum.GROUP_RECALL_ADMIN, uid, request.getUidList(), new ArrayList<>(), roomGroup.getName());
|
||||
setAdminNotice(NoticeTypeEnum.GROUP_RECALL_ADMIN, uid, request.getUidList(), new ArrayList<>(), roomGroup.getRoomId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,7 +418,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
*/
|
||||
// @Async(LUOHUO_EXECUTOR)
|
||||
public void asyncOnline(List<Long> uidList, Long roomId, boolean online) {
|
||||
Set<Long> onlineList = presenceApi.getOnlineUsersList(uidList).getData();
|
||||
Set<Long> onlineList = onlineService.getOnlineUsersList(uidList);
|
||||
if (CollUtil.isEmpty(onlineList)) {
|
||||
return;
|
||||
}
|
||||
@@ -770,7 +772,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
Room room = roomCache.get(roomId);
|
||||
AssertUtil.isNotEmpty(roomGroup, "roomId有误");
|
||||
|
||||
Map<Long, Long> map = presenceApi.getBatchGroupOnlineCounts(Arrays.asList(room.getId())).getData();
|
||||
Map<Long, Long> map = onlineService.getBatchGroupOnlineCounts(Arrays.asList(room.getId()));
|
||||
|
||||
// 获取群成员数、在线人员、备注、我的群名称
|
||||
Long onlineNum = map.get(room.getId());
|
||||
@@ -808,7 +810,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
Map<Long, SummeryInfoDTO> batch = userSummaryCache.getBatch(uids);
|
||||
|
||||
// 5. 批量获取在线状态
|
||||
Set<Long> onlineList = presenceApi.getOnlineUsersList(new ArrayList<>(uids)).getData();
|
||||
Set<Long> onlineList = onlineService.getOnlineUsersList(new ArrayList<>(uids));
|
||||
|
||||
// 6. 填充用户信息和在线状态
|
||||
chatMemberResps.forEach(item -> {
|
||||
@@ -917,7 +919,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
removedUid,
|
||||
uuid,
|
||||
removedUid,
|
||||
roomGroup.getName(),
|
||||
roomGroup.getRoomId(),
|
||||
roomGroup.getName()
|
||||
);
|
||||
|
||||
@@ -930,7 +932,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
managerId,
|
||||
uuid,
|
||||
removedUid,
|
||||
roomGroup.getName(),
|
||||
roomGroup.getRoomId(),
|
||||
roomGroup.getName()
|
||||
));
|
||||
}
|
||||
@@ -979,7 +981,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
invite.getTargetId(),
|
||||
invite.getId(),
|
||||
invite.getTargetId(),
|
||||
roomGroup.getName(),
|
||||
roomGroup.getRoomId(),
|
||||
roomGroup.getName()
|
||||
);
|
||||
|
||||
@@ -991,7 +993,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
managerId,
|
||||
invite.getId(),
|
||||
invite.getTargetId(),
|
||||
roomGroup.getName(),
|
||||
roomGroup.getRoomId(),
|
||||
roomGroup.getName()
|
||||
));
|
||||
});
|
||||
@@ -1033,6 +1035,8 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
ChatMessageReq messageReq = new ChatMessageReq();
|
||||
messageReq.setBody(StrUtil.format("{}解散了群聊", user.getName()));
|
||||
messageReq.setMsgType(MessageTypeEnum.SYSTEM.getType());
|
||||
messageReq.setSkip(true);
|
||||
messageReq.setRoomId(roomId);
|
||||
chatService.sendMsg(messageReq, uid);
|
||||
|
||||
// 4.1 删除房间和群并清除缓存
|
||||
@@ -1056,6 +1060,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
return true;
|
||||
});
|
||||
// 4.5 告知所有人群已经被解散, 这里要走groupMemberDao查询,缓存中可能没有屏蔽群的用户
|
||||
roomCache.delete(roomId);
|
||||
groupMemberCache.evictMemberList(room.getId());
|
||||
groupMemberCache.evictExceptMemberList(room.getId());
|
||||
groupMemberCache.evictAllMemberDetails();
|
||||
@@ -1063,7 +1068,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
CacheKey uKey = PresenceCacheKeyBuilder.userGroupsKey(uid);
|
||||
cachePlusOps.del(uKey, gKey);
|
||||
asyncOnline(memberUidList, room.getId(), false);
|
||||
// pushService.sendPushMsg(RoomAdapter.buildGroupDissolution(roomGroup.getRoomId()), memberUidList, uid);
|
||||
pushService.sendPushMsg(RoomAdapter.buildGroupDissolution(roomGroup.getRoomId()), memberUidList, uid);
|
||||
} else {
|
||||
// 如果房间人员小于3人 那么直接解散群聊
|
||||
if (cachePlusOps.sCard(gKey) <= 3) {
|
||||
@@ -1091,11 +1096,11 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
asyncOnline(Arrays.asList(uid), room.getId(), false);
|
||||
|
||||
// 4.8 发送移除事件告知群成员
|
||||
WsBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), Math.toIntExact(cachePlusOps.sCard(gKey)), Math.toIntExact(cachePlusOps.sCard(PresenceCacheKeyBuilder.onlineGroupMembersKey(room.getId()))), Arrays.asList(uid), WSMemberChange.CHANGE_TYPE_QUIT);
|
||||
pushService.sendPushMsg(ws, memberUidList, uid);
|
||||
groupMemberCache.evictMemberList(room.getId());
|
||||
groupMemberCache.evictExceptMemberList(room.getId());
|
||||
groupMemberCache.evictMemberDetail(room.getId(), uid);
|
||||
WsBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), Math.toIntExact(cachePlusOps.sCard(gKey)), Math.toIntExact(cachePlusOps.sCard(PresenceCacheKeyBuilder.onlineGroupMembersKey(room.getId()))), Arrays.asList(uid), WSMemberChange.CHANGE_TYPE_QUIT);
|
||||
pushService.sendPushMsg(ws, memberUidList, uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1106,6 +1111,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
Map<Long, SummeryInfoDTO> userMap = userSummaryCache.getBatch(request.getUidList());
|
||||
AssertUtil.isTrue(userMap.size() > 1, "群聊人数应大于2人");
|
||||
|
||||
userMap.remove(DefValConstants.DEF_BOT_ID);
|
||||
List<Long> uidList = new ArrayList<>(userMap.keySet());
|
||||
AtomicReference<Long> roomIdAtomic = new AtomicReference(0L);
|
||||
|
||||
@@ -1115,13 +1121,19 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
// 批量保存群成员
|
||||
List<GroupMember> groupMembers = RoomAdapter.buildGroupMemberBatch(uidList, roomGroup.getId());
|
||||
groupMemberDao.saveBatch(groupMembers);
|
||||
|
||||
// 添加所有人的会话
|
||||
uidList.add(uid);
|
||||
for (Long memberId : uidList) {
|
||||
contactDao.refreshOrCreate(roomGroup.getRoomId(), memberId);
|
||||
}
|
||||
|
||||
roomIdAtomic.set(roomGroup.getRoomId());
|
||||
return true;
|
||||
})) {
|
||||
// 发送邀请加群消息 ==> 触发每个人的会话
|
||||
roomGroupCache.evictAllCaches();
|
||||
// 处理新房间里面所有在线人员
|
||||
uidList.add(uid);
|
||||
groupMemberCache.evictMemberList(roomIdAtomic.get());
|
||||
groupMemberCache.evictExceptMemberList(roomIdAtomic.get());
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.luohuo.flex.im.core.chat.service.strategy.msg;
|
||||
|
||||
import com.luohuo.basic.context.ContextUtil;
|
||||
import com.luohuo.basic.utils.SpringUtils;
|
||||
import com.luohuo.basic.utils.TimeUtils;
|
||||
import com.luohuo.flex.im.core.chat.service.cache.MsgCache;
|
||||
import com.luohuo.flex.im.core.chat.service.cache.GroupMemberCache;
|
||||
import com.luohuo.flex.im.core.user.service.cache.UserSummaryCache;
|
||||
import com.luohuo.flex.im.domain.dto.SummeryInfoDTO;
|
||||
import com.luohuo.flex.im.domain.entity.GroupMember;
|
||||
import com.luohuo.flex.im.domain.enums.GroupRoleEnum;
|
||||
import com.luohuo.flex.im.vo.result.tenant.MsgRecallVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.luohuo.flex.im.common.event.MessageRecallEvent;
|
||||
@@ -27,48 +31,83 @@ import java.util.Objects;
|
||||
@AllArgsConstructor
|
||||
public class RecallMsgHandler extends AbstractMsgHandler<Object> {
|
||||
|
||||
private MessageDao messageDao;
|
||||
private MessageDao messageDao;
|
||||
private UserSummaryCache userSummaryCache;
|
||||
private MsgCache msgCache;
|
||||
private GroupMemberCache groupMemberCache;
|
||||
|
||||
@Override
|
||||
MessageTypeEnum getMsgTypeEnum() {
|
||||
return MessageTypeEnum.RECALL;
|
||||
}
|
||||
@Override
|
||||
MessageTypeEnum getMsgTypeEnum() {
|
||||
return MessageTypeEnum.RECALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveMsg(Message msg, Object body) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void saveMsg(Message msg, Object body) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object showMsg(Message msg) {
|
||||
MsgRecallDTO recall = msg.getExtra().getRecall();
|
||||
SummeryInfoDTO userInfo = userSummaryCache.get(recall.getRecallUid());
|
||||
if (!Objects.equals(recall.getRecallUid(), msg.getFromUid())) {
|
||||
return "管理员\"" + userInfo.getName() + "\"撤回了一条成员消息";
|
||||
}
|
||||
return "\"" + userInfo.getName() + "\"撤回了一条消息";
|
||||
}
|
||||
@Override
|
||||
public Object showMsg(Message msg) {
|
||||
MsgRecallDTO recall = msg.getExtra().getRecall();
|
||||
Long recallerUid = recall.getRecallUid();
|
||||
Long senderUid = msg.getFromUid();
|
||||
Long currentUserUid = ContextUtil.getUid();
|
||||
|
||||
@Override
|
||||
public Object showReplyMsg(Message msg) {
|
||||
return "原消息已被撤回";
|
||||
}
|
||||
// 获取撤回者的群成员信息和用户信息
|
||||
GroupMember recallerMember = groupMemberCache.getMemberDetail(msg.getRoomId(), recallerUid);
|
||||
SummeryInfoDTO recallerUserInfo = userSummaryCache.get(recallerUid);
|
||||
|
||||
public void recall(Long recallUid, List<Long> uidList, Message message) {//todo 消息覆盖问题用版本号解决
|
||||
MessageExtra extra = message.getExtra();
|
||||
extra.setRecall(new MsgRecallDTO(recallUid, TimeUtils.getTime(LocalDateTime.now())));
|
||||
Message update = new Message();
|
||||
update.setId(message.getId());
|
||||
update.setType(MessageTypeEnum.RECALL.getType());
|
||||
update.setExtra(extra);
|
||||
messageDao.updateById(update);
|
||||
// 获取被撤回消息发送者的用户信息(用于显示成员名称)
|
||||
SummeryInfoDTO senderUserInfo = userSummaryCache.get(senderUid);
|
||||
|
||||
// 判断关键关系
|
||||
boolean isRecallerCurrentUser = Objects.equals(recallerUid, currentUserUid);
|
||||
boolean isSenderCurrentUser = Objects.equals(senderUid, currentUserUid);
|
||||
|
||||
String roleName = GroupRoleEnum.get(recallerMember.getRoleId());
|
||||
String messageText;
|
||||
|
||||
if (isRecallerCurrentUser) {
|
||||
// 当前用户是撤回操作执行者
|
||||
if (Objects.equals(recallerUid, senderUid)) {
|
||||
// 撤回自己的消息:自己视角
|
||||
messageText = "你撤回了一条消息";
|
||||
} else {
|
||||
// 撤回他人的消息:群主/管理员视角
|
||||
messageText = "你撤回了成员" + senderUserInfo.getName() + "的一条消息";
|
||||
}
|
||||
} else {
|
||||
// 当前用户不是撤回操作执行者
|
||||
if (isSenderCurrentUser) {
|
||||
// 当前用户是被撤回消息的发送者(被撤回者视角)
|
||||
messageText = roleName + recallerUserInfo.getName() + "撤回了你的一条消息";
|
||||
} else {
|
||||
// 当前用户是旁观者(其他成员视角)
|
||||
messageText = roleName + recallerUserInfo.getName() + "撤回了一条消息";
|
||||
}
|
||||
}
|
||||
|
||||
return new MsgRecallVo(messageText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object showReplyMsg(Message msg) {
|
||||
return "原消息已被撤回";
|
||||
}
|
||||
|
||||
public void recall(Long recallUid, List<Long> uidList, Message message) {//todo 消息覆盖问题用版本号解决
|
||||
MessageExtra extra = message.getExtra();
|
||||
extra.setRecall(new MsgRecallDTO(recallUid, TimeUtils.getTime(LocalDateTime.now())));
|
||||
Message update = new Message();
|
||||
update.setId(message.getId());
|
||||
update.setType(MessageTypeEnum.RECALL.getType());
|
||||
update.setExtra(extra);
|
||||
messageDao.updateById(update);
|
||||
SpringUtils.publishEvent(new MessageRecallEvent(this, uidList, new ChatMsgRecallDTO(message.getId(), message.getRoomId(), recallUid)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String showContactMsg(Message msg) {
|
||||
return "撤回了一条消息";
|
||||
}
|
||||
@Override
|
||||
public String showContactMsg(Message msg) {
|
||||
return "撤回了一条消息";
|
||||
// return ((MsgRecallVo) showMsg(msg)).getContent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,13 @@ public class UserFriendDao extends ServiceImpl<UserFriendMapper, UserFriend> {
|
||||
.one();
|
||||
}
|
||||
|
||||
public UserFriend getByFriend2(Long uid1, Long uid2) {
|
||||
return lambdaQuery()
|
||||
.eq(UserFriend::getUid, uid1)
|
||||
.eq(UserFriend::getFriendUid, uid2)
|
||||
.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* 当好友关系变更时清除缓存
|
||||
* @param roomId 房间ID
|
||||
|
||||
@@ -24,7 +24,7 @@ public interface NoticeService {
|
||||
*/
|
||||
void createNotice(RoomTypeEnum applyType, NoticeTypeEnum type, Long senderId, Long receiverId, Long applyId, Long operate, String content);
|
||||
|
||||
void createNotice(RoomTypeEnum applyType, NoticeTypeEnum type, Long senderId, Long receiverId, Long applyId, Long operate, String name, String content);
|
||||
void createNotice(RoomTypeEnum applyType, NoticeTypeEnum type, Long senderId, Long receiverId, Long applyId, Long operate, Long roomId, String content);
|
||||
|
||||
/**
|
||||
* 更新通知状态
|
||||
|
||||
@@ -176,7 +176,7 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
uid,
|
||||
applyId,
|
||||
uid,
|
||||
roomGroup.getName(),
|
||||
roomGroup.getRoomId(),
|
||||
req.getMsg()
|
||||
);
|
||||
|
||||
@@ -188,7 +188,7 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
groupAdminId,
|
||||
applyId,
|
||||
uid,
|
||||
roomGroup.getName(),
|
||||
roomGroup.getRoomId(),
|
||||
req.getMsg()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ import com.google.common.collect.Lists;
|
||||
import com.luohuo.basic.cache.redis.BaseRedis;
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.basic.model.cache.CacheKey;
|
||||
import com.luohuo.flex.common.OnlineService;
|
||||
import com.luohuo.flex.common.cache.FriendCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.cache.PresenceCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.constant.DefValConstants;
|
||||
import com.luohuo.flex.im.api.PresenceApi;
|
||||
import com.luohuo.flex.im.core.user.service.cache.UserSummaryCache;
|
||||
import com.luohuo.flex.im.domain.dto.SummeryInfoDTO;
|
||||
import com.luohuo.flex.im.domain.enums.ApplyReadStatusEnum;
|
||||
@@ -71,7 +71,7 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
private BaseRedis baseRedis;
|
||||
private final PushService pushService;
|
||||
private CachePlusOps cachePlusOps;
|
||||
private PresenceApi presenceApi;
|
||||
private OnlineService onlineService;
|
||||
|
||||
/**
|
||||
* 注入好友关系
|
||||
@@ -205,6 +205,9 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
log.info("没有好友关系:{},{}", uid, friendUid);
|
||||
return;
|
||||
}
|
||||
if (DefValConstants.DEF_BOT_ID.equals(friendUid)) {
|
||||
return;
|
||||
}
|
||||
List<Long> friendRecordIds = userFriends.stream().map(UserFriend::getId).collect(Collectors.toList());
|
||||
userFriendDao.removeByIds(friendRecordIds);
|
||||
// 禁用房间
|
||||
@@ -226,7 +229,7 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
}
|
||||
|
||||
List<Long> friendUids = friendPage.getList().stream().map(UserFriend::getFriendUid).collect(Collectors.toList());
|
||||
Set<Long> onlineList = presenceApi.getOnlineUsersList(friendUids).getData();
|
||||
Set<Long> onlineList = onlineService.getOnlineUsersList(friendUids);
|
||||
return CursorPageBaseResp.init(friendPage, FriendAdapter.buildFriend(friendPage.getList(), onlineList), 0L);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class NoticeServiceImpl implements NoticeService {
|
||||
private void pushNoticeToUser(Long receiverId, Notice notice) {
|
||||
WsBaseResp<NoticeVO> wsMsg = new WsBaseResp<>();
|
||||
wsMsg.setData(convertToVO(notice));
|
||||
wsMsg.setType(WSRespTypeEnum.NOTICE.getType());
|
||||
wsMsg.setType(WSRespTypeEnum.NOTIFY_EVENT.getType());
|
||||
pushService.sendPushMsg(wsMsg, Collections.singletonList(receiverId), notice.getSenderId());
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ public class NoticeServiceImpl implements NoticeService {
|
||||
|
||||
@Override
|
||||
public void createNotice(RoomTypeEnum applyType, NoticeTypeEnum type, Long senderId, Long receiverId, Long applyId, Long operate, String content) {
|
||||
createNotice(applyType, type, senderId, receiverId, applyId, operate, "", content);
|
||||
createNotice(applyType, type, senderId, receiverId, applyId, operate, 0L, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createNotice(RoomTypeEnum applyType, NoticeTypeEnum type, Long senderId, Long receiverId, Long applyId, Long operate, String name, String content) {
|
||||
public void createNotice(RoomTypeEnum applyType, NoticeTypeEnum type, Long senderId, Long receiverId, Long applyId, Long operate, Long roomId, String content) {
|
||||
Notice notice = new Notice();
|
||||
notice.setType(applyType.getType());
|
||||
notice.setEventType(type.getType());
|
||||
@@ -61,7 +61,7 @@ public class NoticeServiceImpl implements NoticeService {
|
||||
notice.setReceiverId(receiverId);
|
||||
notice.setApplyId(applyId);
|
||||
notice.setOperateId(operate);
|
||||
notice.setName(name);
|
||||
notice.setRoomId(roomId);
|
||||
notice.setContent(content);
|
||||
notice.setIsRead(UNREAD.getCode());
|
||||
notice.setStatus(NoticeStatusEnum.UNTREATED.getStatus());
|
||||
@@ -102,7 +102,9 @@ public class NoticeServiceImpl implements NoticeService {
|
||||
public PageBaseResp<NoticeVO> getUserNotices(Long uid, PageBaseReq request) {
|
||||
IPage<Notice> noticeIPage = noticeDao.getUserNotices(uid, true, request.plusPage());
|
||||
// 将这些通知设为已读
|
||||
readNotices(uid, noticeIPage);
|
||||
if(request.getClick()){
|
||||
readNotices(uid, noticeIPage);
|
||||
}
|
||||
return PageBaseResp.init(noticeIPage, noticeIPage.getRecords().stream().map(notice -> convertToVO(notice)).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@@ -113,7 +115,7 @@ public class NoticeServiceImpl implements NoticeService {
|
||||
vo.setSenderId(notice.getSenderId());
|
||||
vo.setReceiverId(notice.getReceiverId());
|
||||
vo.setOperateId(notice.getOperateId());
|
||||
vo.setName(notice.getName());
|
||||
vo.setRoomId(notice.getRoomId());
|
||||
vo.setContent(notice.getContent());
|
||||
vo.setEventType(notice.getEventType());
|
||||
vo.setType(notice.getType());
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.luohuo.basic.model.cache.CacheKey;
|
||||
import com.luohuo.basic.service.MQProducer;
|
||||
import com.luohuo.flex.common.cache.PresenceCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.constant.MqConstant;
|
||||
import com.luohuo.flex.im.domain.DelayRetryTask;
|
||||
import com.luohuo.flex.model.entity.dto.NodePushDTO;
|
||||
import com.luohuo.flex.model.entity.WsBaseResp;
|
||||
import com.luohuo.flex.router.NacosRouterService;
|
||||
@@ -23,7 +24,9 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -50,6 +53,18 @@ public class PushService {
|
||||
@Value("${luohuo.thread.min:4}")
|
||||
private int minThreads;
|
||||
|
||||
@Value("${luohuo.thread.retry.max-count:3}")
|
||||
private Integer maxRetryCount;
|
||||
|
||||
@Value("${luohuo.thread.retry.delay-seconds:3}")
|
||||
private Integer delaySeconds;
|
||||
|
||||
// 延迟任务线程池
|
||||
private ScheduledExecutorService retryScheduler;
|
||||
|
||||
// 重试次数记录
|
||||
private final Map<String, AtomicInteger> messageRetryCountMap = new ConcurrentHashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
int poolSize = Math.max(minThreads, Runtime.getRuntime().availableProcessors() * threadMultiplier);
|
||||
@@ -62,6 +77,13 @@ public class PushService {
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
retryScheduler = Executors.newScheduledThreadPool(2,
|
||||
new ThreadFactoryBuilder()
|
||||
.setNameFormat("push-retry-scheduler")
|
||||
.setDaemon(true)
|
||||
.build());
|
||||
|
||||
log.info("初始化推送线程池, size={}", poolSize);
|
||||
}
|
||||
|
||||
@@ -70,18 +92,23 @@ public class PushService {
|
||||
* @param msg 消息体
|
||||
* @param uids 接收消息的用户
|
||||
* @param cuid 操作人
|
||||
* TODO uids 中没有推送的消息加入延迟信箱
|
||||
* @param retry 延迟推送 [延迟二次推送判断在途消息是否已经ack]
|
||||
* @return
|
||||
*/
|
||||
public CompletableFuture<Void> sendAsync(WsBaseResp<?> msg, List<Long> uids, Long cuid) {
|
||||
public CompletableFuture<Void> sendAsync(WsBaseResp<?> msg, List<Long> uids, Long hashId, Long cuid, Boolean retry) {
|
||||
// 1. 构建三级映射: 节点 → 设备指纹 → 用户ID
|
||||
Map<String, Map<String, Long>> nodeDeviceUser = routerService.findNodeDeviceUser(uids);
|
||||
|
||||
// 2. 按节点+设备批量推送
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
nodeDeviceUser.forEach((nodeId, deviceUserMap) -> futures.add(CompletableFuture.runAsync(
|
||||
() -> mqProducer.sendMsg(MqConstant.PUSH_TOPIC + nodeId, new NodePushDTO(msg, deviceUserMap, cuid)),
|
||||
getExecutorForNode(nodeId)
|
||||
() -> {
|
||||
if (retry) {
|
||||
mqProducer.sendMsgWithDelay(MqConstant.PUSH_DELAY_TOPIC, new NodePushDTO(msg, deviceUserMap, hashId, cuid), delaySeconds);
|
||||
} else {
|
||||
mqProducer.sendMsg(MqConstant.PUSH_TOPIC + nodeId, new NodePushDTO(msg, deviceUserMap, hashId, cuid));
|
||||
}
|
||||
}, getExecutorForNode(nodeId)
|
||||
)));
|
||||
|
||||
// 3. 执行任务
|
||||
@@ -89,7 +116,7 @@ public class PushService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接发送, 单个用户直接推送
|
||||
* 直接发送,单个用户直接推送
|
||||
*/
|
||||
public void sendPushMsg(WsBaseResp<?> msg, Long uid, Long cuid) {
|
||||
sendPushMsg(msg, Arrays.asList(uid), cuid);
|
||||
@@ -97,9 +124,10 @@ public class PushService {
|
||||
|
||||
/**
|
||||
* 批量异步发送给 uidList
|
||||
* TODO 这里hashId 需要重新生成
|
||||
*/
|
||||
public void sendPushMsg(WsBaseResp<?> msg, List<Long> uidList, Long cuid) {
|
||||
sendAsync(msg, uidList, cuid)
|
||||
sendAsync(msg, uidList, 0L, cuid, false)
|
||||
.exceptionally(e -> {
|
||||
log.error("批量推送失败", e);
|
||||
return null;
|
||||
@@ -124,6 +152,8 @@ public class PushService {
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
log.info("开始关闭推送线程池...");
|
||||
|
||||
// 1. 关闭推送线程池
|
||||
Arrays.stream(NODE_EXECUTORS).forEach(executor -> {
|
||||
executor.shutdown();
|
||||
try {
|
||||
@@ -136,7 +166,23 @@ public class PushService {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
log.info("推送线程池已关闭");
|
||||
|
||||
// 2. 关闭延迟调度线程池
|
||||
if (retryScheduler != null) {
|
||||
retryScheduler.shutdown();
|
||||
try {
|
||||
if (!retryScheduler.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
retryScheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
retryScheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// 清理重试状态记录
|
||||
messageRetryCountMap.clear();
|
||||
log.info("推送线程池和重试调度器已关闭");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,4 +230,111 @@ public class PushService {
|
||||
Lists.partition(memberIdList, pageSize).forEach(batch -> sendPushMsg(commonResp, batch, uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量推送方法 [重试专用]
|
||||
*/
|
||||
public void sendPushMsgWithRetry(WsBaseResp<?> msg, List<Long> uidList, Long hashId, Long cuid) {
|
||||
sendAsyncWithRetry(msg, uidList, hashId, cuid)
|
||||
.exceptionally(e -> {
|
||||
log.error("重试的批量推送最终失败", e);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 单用户推送方法 [重试专用]
|
||||
* @param msg 消息实体
|
||||
* @param uid 推送的uid
|
||||
* @param hashId 需要重试的唯一标识
|
||||
* @param cuid 操作人
|
||||
*/
|
||||
public void sendPushMsgWithRetry(WsBaseResp<?> msg, Long uid, Long hashId, Long cuid) {
|
||||
sendPushMsgWithRetry(msg, Arrays.asList(uid), hashId, cuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送带重试机制的推送消息
|
||||
*/
|
||||
public CompletableFuture<Void> sendAsyncWithRetry(WsBaseResp<?> msg, List<Long> uids, Long hashId, Long cuid) {
|
||||
return sendAsync(msg, uids, hashId, cuid, true)
|
||||
.exceptionally(throwable -> {
|
||||
// 首次推送失败,触发延迟重试
|
||||
log.warn("消息首次推送失败,触发延迟重试。uidList: {}, Reason: {}", uids, throwable.getMessage());
|
||||
scheduleDelayRetry(msg, uids, hashId, cuid, 1, "首次推送失败: " + throwable.getMessage());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成消息唯一标识Key
|
||||
*/
|
||||
private String generateMessageKey(WsBaseResp<?> msg, List<Long> targetUids) {
|
||||
String uidListHash = Integer.toHexString(targetUids.hashCode());
|
||||
return String.format("retry_%s_%s_%s",
|
||||
msg.getType(),
|
||||
uidListHash,
|
||||
System.currentTimeMillis() / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调度延迟重试
|
||||
*/
|
||||
private void scheduleDelayRetry(WsBaseResp<?> msg, List<Long> uids, Long hashId, Long cuid, int retryCount, String reason) {
|
||||
String messageKey = generateMessageKey(msg, uids);
|
||||
|
||||
// 检查重试次数
|
||||
if (retryCount > maxRetryCount) {
|
||||
log.error("消息重试已达最大次数[{}],停止重试。Key: {}, Reason: {}", maxRetryCount, messageKey, reason);
|
||||
messageRetryCountMap.remove(messageKey);
|
||||
// 可以在这里添加死信队列处理
|
||||
return;
|
||||
}
|
||||
|
||||
// 记录重试次数
|
||||
messageRetryCountMap.put(messageKey, new AtomicInteger(retryCount));
|
||||
|
||||
// 调度延迟重试
|
||||
DelayRetryTask retryTask = new DelayRetryTask(msg, uids, cuid, hashId, retryCount, reason);
|
||||
retryScheduler.schedule(() -> executeRetry(retryTask, messageKey), delaySeconds, TimeUnit.SECONDS);
|
||||
|
||||
log.info("延迟重试任务已调度。Key: {}, 第{}次重试, 延迟: {}秒", messageKey, retryCount, delaySeconds);
|
||||
}
|
||||
/**
|
||||
* 执行重试推送
|
||||
*/
|
||||
private void executeRetry(DelayRetryTask retryTask, String messageKey) {
|
||||
try {
|
||||
log.info("开始执行延迟重试。Key: {}, 第{}次重试", messageKey, retryTask.getRetryCount());
|
||||
|
||||
// 再次尝试推送
|
||||
sendAsync(retryTask.getOriginalMsg(), retryTask.getTargetUids(), retryTask.getHashId(), retryTask.getOperatorUid(), true)
|
||||
.whenComplete((result, throwable) -> {
|
||||
if (throwable != null) {
|
||||
log.warn("第{}次重试推送失败,准备下一次重试。Key: {}",
|
||||
retryTask.getRetryCount(), messageKey, throwable);
|
||||
|
||||
scheduleDelayRetry(retryTask.getOriginalMsg(),
|
||||
retryTask.getTargetUids(),
|
||||
retryTask.getHashId(),
|
||||
retryTask.getOperatorUid(), retryTask.getRetryCount() + 1,
|
||||
"重试推送失败: " + throwable.getMessage());
|
||||
} else {
|
||||
messageRetryCountMap.remove(messageKey);
|
||||
log.info("第{}次重试推送成功。Key: {}",
|
||||
retryTask.getRetryCount(), messageKey);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("执行延迟重试时发生异常。Key: {}", messageKey, e);
|
||||
// 异常情况下继续重试
|
||||
scheduleDelayRetry(retryTask.getOriginalMsg(),
|
||||
retryTask.getTargetUids(),
|
||||
retryTask.getHashId(),
|
||||
retryTask.getOperatorUid(),
|
||||
retryTask.getRetryCount() + 1,
|
||||
"执行异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ public class UserServiceImpl implements UserService {
|
||||
AssertUtil.equal(itemConfig.getType(), ItemTypeEnum.BADGE.getType(), "该徽章不可佩戴");
|
||||
// 佩戴徽章
|
||||
userDao.wearingBadge(uid, req.getBadgeId());
|
||||
userCache.delete(uid);
|
||||
userSummaryCache.delete(uid);
|
||||
}
|
||||
|
||||
@@ -283,6 +284,7 @@ public class UserServiceImpl implements UserService {
|
||||
boolean save = userDao.updateById(user);
|
||||
if(save){
|
||||
cachePlusOps.hDel("emailCode", req.getUuid());
|
||||
userCache.delete(uid);
|
||||
userSummaryCache.delete(uid);
|
||||
}
|
||||
return save;
|
||||
@@ -308,6 +310,7 @@ public class UserServiceImpl implements UserService {
|
||||
uw.lambda().set(User::getNum, user.getNum() - 1).eq(User::getId, user.getId());
|
||||
boolean success = userDao.update(uw);
|
||||
if(success){
|
||||
userCache.delete(uid);
|
||||
userSummaryCache.delete(uid);
|
||||
}
|
||||
return success;
|
||||
@@ -342,13 +345,14 @@ public class UserServiceImpl implements UserService {
|
||||
// 保存用户
|
||||
newUser.setCreateBy(1L);
|
||||
userDao.save(newUser);
|
||||
// 加上系统机器人好友
|
||||
roomAppService.createSystemFriend(DefValConstants.DEF_ROOM_ID, DefValConstants.DEF_GROUP_ID, newUser.getId());
|
||||
|
||||
// 注入群组信息
|
||||
cachePlusOps.sAdd(PresenceCacheKeyBuilder.groupMembersKey(DefValConstants.DEF_ROOM_ID), newUser.getId());
|
||||
cachePlusOps.sAdd(PresenceCacheKeyBuilder.userGroupsKey(newUser.getId()), DefValConstants.DEF_ROOM_ID);
|
||||
|
||||
// 加上系统机器人好友
|
||||
roomAppService.createSystemFriend(DefValConstants.DEF_ROOM_ID, DefValConstants.DEF_GROUP_ID, newUser.getId());
|
||||
|
||||
// 发布用户注册消息
|
||||
SpringUtils.publishEvent(new UserRegisterEvent(this, newUser));
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.luohuo.flex.im.core.user.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.luohuo.flex.im.core.user.dao.UserStateDao;
|
||||
import com.luohuo.flex.im.core.user.service.cache.UserCache;
|
||||
import com.luohuo.flex.im.domain.entity.UserState;
|
||||
import com.luohuo.flex.model.entity.WSRespTypeEnum;
|
||||
import com.luohuo.flex.im.domain.vo.resp.user.UserInfoResp;
|
||||
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
public class UserStateServiceImpl implements UserStateService {
|
||||
|
||||
private UserStateDao userStateDao;
|
||||
private UserCache userCache;
|
||||
private UserSummaryCache userSummaryCache;
|
||||
private UserService userService;
|
||||
private PushService pushService;
|
||||
@@ -42,17 +43,14 @@ public class UserStateServiceImpl implements UserStateService {
|
||||
}
|
||||
|
||||
UserState userState = userStateDao.getById(userStateId);
|
||||
Boolean changeUserState = userService.changeUserState(uid, userStateId);
|
||||
userService.changeUserState(uid, userStateId);
|
||||
|
||||
if (ObjectUtil.isNotNull(userState) && changeUserState){
|
||||
// 1.清除缓存
|
||||
userSummaryCache.delete(uid);
|
||||
// 1.清除缓存
|
||||
userCache.delete(uid);
|
||||
userSummaryCache.delete(uid);
|
||||
|
||||
// 2.推送数据
|
||||
pushService.pushRoom(uid, WSRespTypeEnum.USER_STATE_CHANGE.getType(), new UserStateVo(uid, userState.getId()));
|
||||
return true;
|
||||
}else {
|
||||
throw new RuntimeException("用户状态更新失败");
|
||||
}
|
||||
// 2.推送数据
|
||||
pushService.pushRoom(uid, WSRespTypeEnum.USER_STATE_CHANGE.getType(), new UserStateVo(uid, userState == null? 0L: userState.getId()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,19 @@
|
||||
active_time = VALUES(active_time)
|
||||
</insert>
|
||||
|
||||
<!-- 执行这个sql是因为前端有消息没被收到,每次更新当前会话未收到的消息时只更新最小的id那个 -->
|
||||
<insert id="refreshOrCreateActive">
|
||||
INSERT INTO im_contact (room_id, uid, last_msg_id, active_time, is_del) VALUES
|
||||
<foreach collection="memberUidList" item="uid" separator=",">
|
||||
(#{roomId},#{uid},#{msgId},#{activeTime},0)
|
||||
</foreach>
|
||||
ON DUPLICATE KEY UPDATE
|
||||
is_del = IF(#{msgId} < last_msg_id, 0, is_del),
|
||||
hide = IF(#{msgId} < last_msg_id, 0, hide),
|
||||
last_msg_id = IF(#{msgId} < last_msg_id, VALUES(last_msg_id), last_msg_id),
|
||||
active_time = IF(#{msgId} < last_msg_id, VALUES(active_time), active_time)
|
||||
</insert>
|
||||
|
||||
<insert id="refreshOrCreate">
|
||||
INSERT INTO im_contact (room_id, uid, is_del) VALUES (#{roomId},#{uid},0)
|
||||
ON DUPLICATE KEY UPDATE is_del = 0, hide = 0
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-im</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -57,12 +57,12 @@ public class ChatController {
|
||||
}
|
||||
|
||||
@PostMapping("/msg/list")
|
||||
@Operation(summary ="消息列表")
|
||||
@Operation(summary ="消息列表 [登录时消息同步用的]")
|
||||
// @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||
public R<List<ChatMessageResp>> getMsgPage(@RequestBody MsgReq msgReq) {
|
||||
List<ChatMessageResp> msgPage = chatService.getMsgList(msgReq, ContextUtil.getUid());
|
||||
// Set<String> blackMembers = getBlackUidSet();
|
||||
// msgPage.removeIf(a -> blackMembers.contains(a.getFromUser().getUid().toString()));
|
||||
Set<String> blackMembers = getBlackUidSet();
|
||||
msgPage.removeIf(a -> blackMembers.contains(a.getFromUser().getUid().toString()));
|
||||
return R.success(msgPage);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-im</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.luohuo.flex.im.domain;
|
||||
|
||||
import com.luohuo.flex.model.entity.WsBaseResp;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class DelayRetryTask {
|
||||
// 原始消息
|
||||
private WsBaseResp<?> originalMsg;
|
||||
// 目标用户
|
||||
private List<Long> targetUids;
|
||||
// 操作者
|
||||
private Long operatorUid;
|
||||
// 哈希值
|
||||
private Long hashId;
|
||||
// 重试次数
|
||||
private Integer retryCount;
|
||||
private String retryReason;
|
||||
}
|
||||
@@ -48,8 +48,8 @@ public class Notice extends Entity<Long> {
|
||||
@TableField("operate_id")
|
||||
private Long operateId;
|
||||
|
||||
@Schema(description = "群聊的名称")
|
||||
private String name;
|
||||
@Schema(description = "房间id")
|
||||
private Long roomId;
|
||||
|
||||
@Schema(description = "通知内容 申请时填写的, 进群、移除时是群聊的名称")
|
||||
private String content;
|
||||
|
||||
@@ -16,9 +16,6 @@ import java.util.stream.Collectors;
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum GroupRoleEnum {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
LEADER(1, "群主"),
|
||||
MANAGER(2, "管理"),
|
||||
MEMBER(3, "普通成员"),
|
||||
@@ -27,9 +24,6 @@ public enum GroupRoleEnum {
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
public static final List<Integer> ADMIN_LIST = Arrays.asList(GroupRoleEnum.LEADER.getType(), GroupRoleEnum.MANAGER.getType());
|
||||
public static final List<Integer> ROLE_LIST = Arrays.asList(GroupRoleEnum.LEADER.getType(), GroupRoleEnum.MANAGER.getType(), GroupRoleEnum.MEMBER.getType());
|
||||
|
||||
private static Map<Integer, GroupRoleEnum> cache;
|
||||
|
||||
static {
|
||||
@@ -39,4 +33,15 @@ public enum GroupRoleEnum {
|
||||
public static GroupRoleEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回角色的名称
|
||||
* @param type 传入成员类型
|
||||
*/
|
||||
public static String get(Integer type) {
|
||||
if(type > MANAGER.getType()){
|
||||
return "";
|
||||
}
|
||||
return cache.get(type).getDesc();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@@ -24,6 +25,9 @@ public class PageBaseReq implements Serializable {
|
||||
@Schema(description = "页面索引(从1开始)")
|
||||
private Integer pageNo = 1;
|
||||
|
||||
@Schema(description = "点击请求")
|
||||
private Boolean click = false;
|
||||
|
||||
/**
|
||||
* 获取mybatisPlus的page
|
||||
*/
|
||||
|
||||
@@ -18,9 +18,9 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MsgReq implements Serializable {
|
||||
@Schema(description ="消息id")
|
||||
@Schema(description ="消息id, 传了消息id默认就是查询消息的接口")
|
||||
private List<Long> msgIds;
|
||||
|
||||
@Schema(description ="最后一次ws连接的时间")
|
||||
private Long lastOptTime;
|
||||
@Schema(description ="开启同步消息")
|
||||
private Boolean async = false;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ public class NoticeVO {
|
||||
@Schema(description = "被操作的人")
|
||||
private Long operateId;
|
||||
|
||||
@Schema(description = "群昵称")
|
||||
private String name;
|
||||
@Schema(description = "房间id")
|
||||
private Long roomId;
|
||||
|
||||
@Schema(description = "通知内容 申请时填写的")
|
||||
private String content;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.luohuo.flex.im.vo.result.tenant;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 消息撤回
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
public class MsgRecallVo implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String content;
|
||||
|
||||
public MsgRecallVo(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-im-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-im-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-im-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-im</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-im</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -3,6 +3,19 @@ package com.luohuo.flex.areatest;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.TimeInterval;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.luohuo.basic.context.ContextUtil;
|
||||
import com.luohuo.flex.im.core.chat.dao.ContactDao;
|
||||
import com.luohuo.flex.im.core.chat.dao.GroupMemberDao;
|
||||
import com.luohuo.flex.im.core.chat.dao.RoomGroupDao;
|
||||
import com.luohuo.flex.im.core.chat.service.RoomService;
|
||||
import com.luohuo.flex.im.core.chat.service.impl.ChatServiceImpl;
|
||||
import com.luohuo.flex.im.core.user.dao.UserDao;
|
||||
import com.luohuo.flex.im.core.user.dao.UserFriendDao;
|
||||
import com.luohuo.flex.im.core.user.service.impl.FriendServiceImpl;
|
||||
import com.luohuo.flex.im.domain.entity.Contact;
|
||||
import com.luohuo.flex.im.domain.entity.GroupMember;
|
||||
import com.luohuo.flex.im.domain.entity.RoomGroup;
|
||||
import com.luohuo.flex.im.domain.entity.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -22,11 +35,47 @@ public class CityParserTest {
|
||||
CityParser cityParser;
|
||||
@Resource
|
||||
SqlCityParserDecorator sqlCityParserDecorator;
|
||||
@Resource
|
||||
UserDao userDao;
|
||||
@Resource
|
||||
UserFriendDao userFriendDao;
|
||||
@Resource
|
||||
ChatServiceImpl chatService;
|
||||
@Resource
|
||||
private RoomService roomService;
|
||||
@Resource
|
||||
private GroupMemberDao groupMemberDao;
|
||||
@Resource
|
||||
private RoomGroupDao roomGroupDao;
|
||||
@Resource
|
||||
private ContactDao contactDao;
|
||||
@Resource
|
||||
private FriendServiceImpl friendService;
|
||||
@Test
|
||||
public void bot() {
|
||||
ContextUtil.setUid(1L);
|
||||
ContextUtil.setTenantId(1L);
|
||||
// 2. 计算会话的最后一条消息id
|
||||
List<User> list = userDao.list();
|
||||
list.forEach(user -> {
|
||||
List<GroupMember> groupList = groupMemberDao.getSelfGroup(user.getId());
|
||||
groupList.forEach(groupMember -> {
|
||||
RoomGroup roomGroup = roomGroupDao.getById(groupMember.getGroupId());
|
||||
|
||||
if(roomGroup!=null){
|
||||
Contact contact = contactDao.get(user.getId(), roomGroup.getRoomId());
|
||||
if(contact == null){
|
||||
// 创建会话
|
||||
chatService.createContact(user.getId(), roomGroup.getRoomId());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时爬取最新的地区数据,请执行该方法
|
||||
*/
|
||||
/**
|
||||
* 实时爬取最新的地区数据,请执行该方法
|
||||
*/
|
||||
@Test
|
||||
public void pullArea() {
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../luohuo-dependencies-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-oauth</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -49,6 +49,7 @@ public class RefreshTokenGranter {
|
||||
public LoginResultVO refresh(String refreshToken) {
|
||||
// 1、验证
|
||||
Object str = SaTempUtil.parseToken(refreshToken);
|
||||
SaTempUtil.deleteToken(refreshToken);
|
||||
|
||||
JSONObject obj = JSONUtil.parseObj(str);
|
||||
Long userId = obj.getLong(JWT_KEY_USER_ID);
|
||||
@@ -102,6 +103,7 @@ public class RefreshTokenGranter {
|
||||
resultVO.setToken(tokenSession.getToken());
|
||||
resultVO.setExpire(StpUtil.getTokenTimeout());
|
||||
resultVO.setClient(device);
|
||||
resultVO.setUid(uid);
|
||||
resultVO.setRefreshToken(SaTempUtil.createToken(obj.toString(), 2 * saTokenConfig.getTimeout()));
|
||||
return resultVO;
|
||||
}
|
||||
|
||||
@@ -144,8 +144,9 @@ public class CaptchaServiceImpl implements CaptchaService {
|
||||
|
||||
String code = RandomUtil.randomNumbers(6);
|
||||
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(bindEmailReq.getEmail(), bindEmailReq.getTemplateCode());
|
||||
cacheOps.set(cacheKey, code);
|
||||
ArgumentAssert.isFalse(cacheOps.exists(cacheKey), "请勿重复发送验证码");
|
||||
|
||||
cacheOps.set(cacheKey, code);
|
||||
log.info("邮件验证码 cacheKey={}, code={}", cacheKey, code);
|
||||
|
||||
// 在「运营平台」-「消息模板」配置一个「模板标识」为 templateCode, 且「模板内容」中需要有 code 占位符
|
||||
|
||||
@@ -101,7 +101,13 @@ public class UserInfoServiceImpl implements UserInfoService {
|
||||
}
|
||||
ArgumentAssert.equals(register.getConfirmPassword(), register.getPassword(), "密码和确认密码不一致");
|
||||
DefUser defUser = BeanUtil.toBean(register, DefUser.class);
|
||||
defUserService.registerByEmail(defUser);
|
||||
try {
|
||||
defUserService.registerByEmail(defUser);
|
||||
} catch (Exception e) {
|
||||
if(e.getMessage().contains("Duplicate")){
|
||||
throw new BizException("账号已存在!");
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 根据注册系统构造子系统需要的user参数
|
||||
return switch (LoginEnum.get(register.getSystemType())) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-oauth</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-oauth</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-oauth-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-oauth-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-oauth-facade</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-oauth</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luohuo-oauth</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-dependencies-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../luohuo-dependencies-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>luohuo-presence</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>luohuo-presence-biz</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>基础服务-业务模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-presence-entity</artifactId>
|
||||
<version>${luohuo-project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.basic</groupId>
|
||||
<artifactId>luohuo-cache-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-database-mode</artifactId>
|
||||
<version>${luohuo-project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.basic</groupId>
|
||||
<artifactId>luohuo-databases</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.basic</groupId>
|
||||
<artifactId>luohuo-mvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>jboss-annotations-api_1.3_spec</artifactId>
|
||||
<groupId>org.jboss.spec.javax.annotation</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- @RefreshScope 需要使用 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-email</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- groovy-all -->
|
||||
<dependency>
|
||||
<groupId>org.apache.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>luohuo-presence</artifactId>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<version>2.6.15</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>luohuo-presence-controller</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>基础服务-控制器模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.luohuo.flex</groupId>
|
||||
<artifactId>luohuo-presence-biz</artifactId>
|
||||
<version>${luohuo-project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user