Compare commits
2 Commits
7984b7bc65
...
c1a5340a73
Author | SHA1 | Date | |
---|---|---|---|
c1a5340a73 | |||
33dbe4ec6c |
@ -447,6 +447,8 @@
|
|||||||
}
|
}
|
||||||
await sendMessage(msg)
|
await sendMessage(msg)
|
||||||
messages.success('转接成功')
|
messages.success('转接成功')
|
||||||
|
|
||||||
|
conversation.value = null
|
||||||
} finally {
|
} finally {
|
||||||
// todo 刷新会话列表
|
// todo 刷新会话列表
|
||||||
}
|
}
|
||||||
|
@ -153,30 +153,93 @@
|
|||||||
|
|
||||||
|
|
||||||
// ======================= WebSocket start =======================
|
// ======================= WebSocket start =======================
|
||||||
const server = ref(
|
const server = ref(
|
||||||
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
||||||
'?token=' +
|
'?token=' +
|
||||||
getRefreshToken() // 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
getRefreshToken() // 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
||||||
) // WebSocket 服务地址
|
) // WebSocket 服务地址
|
||||||
|
|
||||||
const chick = ref('2')
|
|
||||||
const userInfo = async () =>{
|
|
||||||
chick.value = '1'
|
|
||||||
user.value = await UserApi.getUserInfo(userId.value)
|
|
||||||
}
|
|
||||||
const zuoji = () =>{
|
|
||||||
chick.value = '2'
|
|
||||||
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
|
|
||||||
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let a = 0;
|
||||||
|
|
||||||
|
const {status, data, send, open, close} = useWebSocket(server.value, {
|
||||||
/** 发起 WebSocket 连接 */
|
onConnected: function (ws) {
|
||||||
const {data, close, open} = useWebSocket(server.value, {
|
console.log('websocket 连接成功!', ws);
|
||||||
autoReconnect: false,
|
},
|
||||||
heartbeat: true
|
onDisconnected: function (ws, event) {
|
||||||
})
|
console.log('WebSocket 连接断开', event);
|
||||||
|
},
|
||||||
|
onError: function (ws, event) {
|
||||||
|
console.error('WebSocket 连接错误:', event);
|
||||||
|
if (event instanceof ErrorEvent) {
|
||||||
|
console.error('详细错误信息:', event.message);
|
||||||
|
} else {
|
||||||
|
console.error('非标准错误:', event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onMessage: function (ws, event) {
|
||||||
|
console.log('收到的 WebSocket 消息:', event.data);
|
||||||
|
a = a + 1 ;
|
||||||
|
if(a == 2){
|
||||||
|
getConversationList()
|
||||||
|
keFuChatBoxRef.value?.refreshMessageList()
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果收到的数据存在
|
||||||
|
// if (event.data) {
|
||||||
|
// let parsedData;
|
||||||
|
|
||||||
|
// // 尝试解析消息
|
||||||
|
// try {
|
||||||
|
// parsedData = JSON.parse(event.data);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error('JSON 解析错误:', error, '原始数据:', event.data);
|
||||||
|
// return; // 如果解析失败,跳过后续处理
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 根据消息的 type 类型来处理不同的消息
|
||||||
|
// const { type } = parsedData;
|
||||||
|
// if (!type) {
|
||||||
|
// console.warn('收到未定义类型的消息:', parsedData);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 示例:处理特定类型的消息
|
||||||
|
// switch (type) {
|
||||||
|
// case 'pong':
|
||||||
|
// // 处理心跳消息
|
||||||
|
// console.log('收到心跳 ping 消息');
|
||||||
|
// // 如果需要回复 pong,可以在这里发送消息
|
||||||
|
// send(JSON.stringify({ type: 'pong' }));
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case 'chat':
|
||||||
|
// // 处理聊天消息
|
||||||
|
// console.log('收到聊天消息:', parsedData.content);
|
||||||
|
// // 处理聊天消息的逻辑
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case 'notification':
|
||||||
|
// // 处理通知消息
|
||||||
|
// console.log('收到通知消息:', parsedData.message);
|
||||||
|
// // 执行通知操作
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// console.warn('收到未知类型的消息:', type);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// console.warn('接收到空数据:', event);
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
autoReconnect: false, // 开启自动重连
|
||||||
|
heartbeat: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 监听 WebSocket 数据 */
|
/** 监听 WebSocket 数据 */
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
@ -188,7 +251,7 @@
|
|||||||
if (data.value === 'pong') {
|
if (data.value === 'pong') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.1 解析 type 消息类型
|
// 2.1 解析 type 消息类型
|
||||||
const jsonMessage = JSON.parse(data.value)
|
const jsonMessage = JSON.parse(data.value)
|
||||||
const type = jsonMessage.type
|
const type = jsonMessage.type
|
||||||
@ -215,6 +278,8 @@
|
|||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// ======================= WebSocket end =======================
|
// ======================= WebSocket end =======================
|
||||||
/** 加载会话列表 */
|
/** 加载会话列表 */
|
||||||
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
||||||
@ -237,18 +302,32 @@
|
|||||||
window.close();
|
window.close();
|
||||||
// window.location.href = '/kefu/support-staff';
|
// window.location.href = '/kefu/support-staff';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const chick = ref('2')
|
||||||
|
const userInfo = async () =>{
|
||||||
|
chick.value = '1'
|
||||||
|
user.value = await UserApi.getUserInfo(userId.value)
|
||||||
|
}
|
||||||
|
const zuoji = () =>{
|
||||||
|
chick.value = '2'
|
||||||
|
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
|
||||||
|
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
|
||||||
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getConversationList()
|
getConversationList()
|
||||||
// 打开 websocket 连接
|
// 打开 websocket 连接
|
||||||
open()
|
open()
|
||||||
|
console.log('WebSocket 已初始化');
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 销毁 */
|
/** 销毁 */
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
// 关闭 websocket 连接
|
// 关闭 websocket 连接
|
||||||
close()
|
close()
|
||||||
|
console.log('WebSocket 已关闭');
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -29,6 +29,6 @@ public class WebSocketProperties {
|
|||||||
* 可选值:local、redis、rocketmq、kafka、rabbitmq
|
* 可选值:local、redis、rocketmq、kafka、rabbitmq
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "WebSocket 的消息发送者不能为空")
|
@NotNull(message = "WebSocket 的消息发送者不能为空")
|
||||||
private String senderType = "local";
|
private String senderType = "redis";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
|
|||||||
import cn.iocoder.yudao.framework.websocket.core.handler.JsonWebSocketMessageHandler;
|
import cn.iocoder.yudao.framework.websocket.core.handler.JsonWebSocketMessageHandler;
|
||||||
import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
|
import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
|
||||||
import cn.iocoder.yudao.framework.websocket.core.security.LoginUserHandshakeInterceptor;
|
import cn.iocoder.yudao.framework.websocket.core.security.LoginUserHandshakeInterceptor;
|
||||||
|
import cn.iocoder.yudao.framework.websocket.core.security.WebSocketAuthorizeRequestsCustomizer;
|
||||||
import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer;
|
import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer;
|
||||||
import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender;
|
import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender;
|
||||||
import cn.iocoder.yudao.framework.websocket.core.sender.local.LocalWebSocketMessageSender;
|
import cn.iocoder.yudao.framework.websocket.core.sender.local.LocalWebSocketMessageSender;
|
||||||
@ -76,10 +77,15 @@ public class YudaoWebSocketAutoConfiguration {
|
|||||||
return new WebSocketSessionManagerImpl();
|
return new WebSocketSessionManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebSocketAuthorizeRequestsCustomizer webSocketAuthorizeRequestsCustomizer(WebSocketProperties webSocketProperties) {
|
||||||
|
return new WebSocketAuthorizeRequestsCustomizer(webSocketProperties);
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== Sender 相关 ====================
|
// ==================== Sender 相关 ====================
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local")
|
||||||
public class LocalWebSocketMessageSenderConfiguration {
|
public class LocalWebSocketMessageSenderConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -90,7 +96,7 @@ public class YudaoWebSocketAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis")
|
||||||
public class RedisWebSocketMessageSenderConfiguration {
|
public class RedisWebSocketMessageSenderConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -108,7 +114,7 @@ public class YudaoWebSocketAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq")
|
||||||
public class RocketMQWebSocketMessageSenderConfiguration {
|
public class RocketMQWebSocketMessageSenderConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -127,7 +133,7 @@ public class YudaoWebSocketAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq")
|
||||||
public class RabbitMQWebSocketMessageSenderConfiguration {
|
public class RabbitMQWebSocketMessageSenderConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -156,7 +162,7 @@ public class YudaoWebSocketAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka")
|
||||||
public class KafkaWebSocketMessageSenderConfiguration {
|
public class KafkaWebSocketMessageSenderConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -21,4 +21,4 @@ public class WebSocketAuthorizeRequestsCustomizer extends AuthorizeRequestsCusto
|
|||||||
registry.antMatchers(webSocketProperties.getPath()).permitAll();
|
registry.antMatchers(webSocketProperties.getPath()).permitAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -43,7 +43,7 @@ public interface WebSocketSenderApi {
|
|||||||
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendObject(Integer userType, String messageType, Object messageContent) {
|
default void sendObject(Integer userType, String messageType, Object messageContent) { //用户发送消息
|
||||||
send(userType, messageType, JsonUtils.toJsonString(messageContent));
|
send(userType, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,12 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-module-system-biz</artifactId>
|
||||||
|
<version>2.1.0-jdk8-snapshot</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -28,4 +28,8 @@ public class AppDiyTemplatePropertyRespVO {
|
|||||||
@JsonRawValue
|
@JsonRawValue
|
||||||
private String user;
|
private String user;
|
||||||
|
|
||||||
|
private String goodsType;
|
||||||
|
|
||||||
|
private String themeType;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,4 +61,11 @@ public class DiyTemplateDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private String property;
|
private String property;
|
||||||
|
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String goodsType;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String themeType;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,15 @@ import cn.iocoder.yudao.module.promotion.convert.diy.DiyPageConvert;
|
|||||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyTemplateConvert;
|
import cn.iocoder.yudao.module.promotion.convert.diy.DiyTemplateConvert;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.diy.DiyTemplateMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.diy.DiyTemplateMapper;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
@ -36,6 +39,9 @@ public class DiyTemplateServiceImpl implements DiyTemplateService {
|
|||||||
@Resource
|
@Resource
|
||||||
private DiyPageService diyPageService;
|
private DiyPageService diyPageService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DictDataApi dictDataApi;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public Long createDiyTemplate(DiyTemplateCreateReqVO createReqVO) {
|
public Long createDiyTemplate(DiyTemplateCreateReqVO createReqVO) {
|
||||||
@ -165,7 +171,17 @@ public class DiyTemplateServiceImpl implements DiyTemplateService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DiyTemplateDO getUsedDiyTemplate() {
|
public DiyTemplateDO getUsedDiyTemplate() {
|
||||||
return diyTemplateMapper.selectByUsed(true);
|
DiyTemplateDO diyTemplateDO = diyTemplateMapper.selectByUsed(true);
|
||||||
|
|
||||||
|
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-theme");
|
||||||
|
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||||
|
diyTemplateDO.setThemeType(dictDataRespDTO.getValue());
|
||||||
|
|
||||||
|
List<DictDataRespDTO> dictDataList1 = dictDataApi.getDictDataList("diy-template-goods");
|
||||||
|
DictDataRespDTO dictDataRespDTO1 = dictDataList1.get(0);
|
||||||
|
diyTemplateDO.setGoodsType(dictDataRespDTO1.getValue());
|
||||||
|
|
||||||
|
return diyTemplateDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ public interface KeFuMessageService {
|
|||||||
* @return 编号
|
* @return 编号
|
||||||
*/
|
*/
|
||||||
Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO);
|
Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO);
|
||||||
|
|
||||||
|
|
||||||
String sendKefuMessageTest(String s);
|
String sendKefuMessageTest(String s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||||
|
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||||
@ -16,7 +17,10 @@ import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuM
|
|||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
||||||
|
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -51,9 +55,12 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
@Resource
|
@Resource
|
||||||
private WebSocketSenderApi webSocketSenderApi;
|
private WebSocketSenderApi webSocketSenderApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private NotifyMessageMapper notifyMessageMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) {
|
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) { //客服发消息
|
||||||
// 1.1 校验会话是否存在
|
// 1.1 校验会话是否存在
|
||||||
KeFuConversationDO conversation = conversationService.validateKefuConversationExists(sendReqVO.getConversationId());
|
KeFuConversationDO conversation = conversationService.validateKefuConversationExists(sendReqVO.getConversationId());
|
||||||
// 1.2 校验接收人是否存在
|
// 1.2 校验接收人是否存在
|
||||||
@ -74,20 +81,39 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) {
|
public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) { //用户发消息
|
||||||
// 1.1 设置会话编号
|
// 1.1 设置会话编号
|
||||||
KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class);
|
KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class);
|
||||||
KeFuConversationDO conversation = conversationService.getOrCreateConversation(sendReqVO.getSenderId());
|
KeFuConversationDO conversation = conversationService.getOrCreateConversation(sendReqVO.getSenderId());
|
||||||
kefuMessage.setConversationId(conversation.getId());
|
kefuMessage.setConversationId(conversation.getId());
|
||||||
// 1.2 保存消息
|
// 1.2 保存消息
|
||||||
|
kefuMessage.setReceiverId(conversation.getKefuId()).setReceiverType(UserTypeEnum.ADMIN.getValue()); // 设置接收人
|
||||||
keFuMessageMapper.insert(kefuMessage);
|
keFuMessageMapper.insert(kefuMessage);
|
||||||
|
|
||||||
// 2. 更新会话消息冗余
|
// 2. 更新会话消息冗余
|
||||||
conversationService.updateConversationLastMessage(kefuMessage);
|
conversationService.updateConversationLastMessage(kefuMessage);
|
||||||
|
|
||||||
|
getSelf().sendAsyncMessageToMembers(conversation.getKefuId(), KEFU_MESSAGE_TYPE, kefuMessage);
|
||||||
|
|
||||||
// 3. 通知所有管理员更新对话
|
// 3. 通知所有管理员更新对话
|
||||||
getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, kefuMessage);
|
getSelf().sendAsyncMessageToAdmins(KEFU_MESSAGE_TYPE, kefuMessage);
|
||||||
return kefuMessage.getId();
|
return kefuMessage.getId();
|
||||||
}
|
}
|
||||||
|
//添加站内信
|
||||||
|
// MemberUserRespDTO user = memberUserApi.getUser(sendReqVO.getSenderId());
|
||||||
|
// NotifyMessageDO notifyMessageDO = new NotifyMessageDO()
|
||||||
|
// .setUserId(sendReqVO.getSenderId())
|
||||||
|
// .setUserType(sendReqVO.getSenderType())
|
||||||
|
// .setTemplateId((long)1)
|
||||||
|
// .setTemplateCode()
|
||||||
|
// .setTemplateNickname(user.getNickname())
|
||||||
|
// .setTemplateContent("客户发来消息")
|
||||||
|
// .setTemplateType(2)
|
||||||
|
// .setTemplateParams()
|
||||||
|
// .setReadStatus(2);
|
||||||
|
// notifyMessageMapper.insert(notifyMessageDO);
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sendKefuMessageTest(String s){
|
public String sendKefuMessageTest(String s){
|
||||||
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), 1L, "1", s);;
|
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), 1L, "1", s);;
|
||||||
@ -137,11 +163,21 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), userId, messageType, content);
|
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), userId, messageType, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
public void sendAsyncMessageToMembers(Long userId, String messageType, Object content) {
|
||||||
|
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), userId, messageType, content);
|
||||||
|
}
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
public void sendAsyncMessageToAdmin(String messageType, Object content) {
|
public void sendAsyncMessageToAdmin(String messageType, Object content) {
|
||||||
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), messageType, content);
|
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), messageType, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
public void sendAsyncMessageToAdmins(String messageType, Object content) {
|
||||||
|
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), messageType, content);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO) {
|
public PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO) {
|
||||||
return keFuMessageMapper.selectPage(pageReqVO);
|
return keFuMessageMapper.selectPage(pageReqVO);
|
||||||
|
@ -27,4 +27,7 @@ public interface NotifyMessageSendApi {
|
|||||||
*/
|
*/
|
||||||
Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO);
|
Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,12 @@ public class DictDataController {
|
|||||||
@Resource
|
@Resource
|
||||||
private DictDataService dictDataService;
|
private DictDataService dictDataService;
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
public DictDataApi dictDataApi;
|
public DictDataApi dictDataApi;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "新增字典数据")
|
@Operation(summary = "新增字典数据")
|
||||||
@PreAuthorize("@ss.hasPermission('system:dict:create')")
|
@PreAuthorize("@ss.hasPermission('system:dict:create')")
|
||||||
@ -159,6 +161,54 @@ public class DictDataController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改装修商品分类字典数据
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/diy-template-goods")
|
||||||
|
public CommonResult<String> setGoods(String id) {
|
||||||
|
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-goods");
|
||||||
|
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||||
|
DictDataSaveReqVO dictDataSaveReqVO = BeanUtils.toBean(dictDataRespDTO, DictDataSaveReqVO.class);
|
||||||
|
dictDataSaveReqVO.setValue(id);
|
||||||
|
dictDataService.updateDictData(dictDataSaveReqVO);
|
||||||
|
return success(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改装修商品分类字典数据
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/getGoods")
|
||||||
|
public CommonResult<String> getGoods() {
|
||||||
|
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-goods");
|
||||||
|
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||||
|
return success(dictDataRespDTO.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改装修装修风格字典数据
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/diy-template-theme")
|
||||||
|
public CommonResult<String> setTheme(String id) {
|
||||||
|
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-theme");
|
||||||
|
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||||
|
DictDataSaveReqVO dictDataSaveReqVO = BeanUtils.toBean(dictDataRespDTO, DictDataSaveReqVO.class);
|
||||||
|
dictDataSaveReqVO.setValue(id);
|
||||||
|
dictDataService.updateDictData(dictDataSaveReqVO);
|
||||||
|
return success(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改装修装修风格字典数据
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/getTheme")
|
||||||
|
public CommonResult<String> getTheme() {
|
||||||
|
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-theme");
|
||||||
|
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||||
|
return success(dictDataRespDTO.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ yudao:
|
|||||||
websocket:
|
websocket:
|
||||||
enable: true # websocket的开关
|
enable: true # websocket的开关
|
||||||
path: /infra/ws # 路径
|
path: /infra/ws # 路径
|
||||||
sender-type: local # 消息发送的类型,可选值为 local、redis、rocketmq、kafka、rabbitmq
|
sender-type: redis # 消息发送的类型,可选值为 local、redis、rocketmq、kafka、rabbitmq
|
||||||
sender-rocketmq:
|
sender-rocketmq:
|
||||||
topic: ${spring.application.name}-websocket # 消息发送的 RocketMQ Topic
|
topic: ${spring.application.name}-websocket # 消息发送的 RocketMQ Topic
|
||||||
consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 RocketMQ Consumer Group
|
consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 RocketMQ Consumer Group
|
||||||
|
Loading…
Reference in New Issue
Block a user