feat: 产品中心

This commit is contained in:
曹鹏飞 2025-05-26 11:33:10 +08:00
parent 485ed4d8b1
commit 1d493b3b2f
26 changed files with 543 additions and 187 deletions

View File

@ -27,6 +27,7 @@ import com.nflg.mobilebroken.repository.service.ILanguageService;
import com.nflg.mobilebroken.repository.service.IWebComponentService;
import com.nflg.mobilebroken.repository.service.IWebComponentTranslateService;
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@ -55,6 +56,7 @@ import java.util.stream.Collectors;
*
* @author 曹鹏飞
*/
@Slf4j
@RestController
@RequestMapping("/multilingual")
public class MultilingualController extends ControllerBase {
@ -204,8 +206,15 @@ public class MultilingualController extends ControllerBase {
List<Map<String, Object>> datas = EecExcelUtil.readTo(file.getInputStream());
List<Language> languages = languageService.getLanguages();
datas.forEach(d -> {
String moduleCode = (String) d.get("模块编号");
String pageCode = (String) d.get("页面编号");
String componentCode = (String) d.get("组件编号");
WebComponent webComponent = webComponentService.lambdaQuery().eq(WebComponent::getComponentCode, componentCode).one();
log.info("模块编号:{},页面编号:{},组件编号:{}",moduleCode,pageCode,componentCode);
WebComponent webComponent = webComponentService.lambdaQuery()
.eq(WebComponent::getModuleCode, moduleCode)
.eq(WebComponent::getPageCode, pageCode)
.eq(WebComponent::getComponentCode, componentCode)
.one();
if (Objects.nonNull(webComponent)) {
d.remove("模块");
d.remove("模块编号");

View File

@ -1,7 +1,9 @@
package com.nflg.mobilebroken.admin.controller;
import com.nflg.mobilebroken.admin.service.DeviceQRCodeService;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.service.ITicketCallService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -21,6 +23,9 @@ public class TestController extends ControllerBase{
@Resource
private DeviceQRCodeService deviceQRCodeService;
@Resource
private ITicketCallService ticketCallService;
/**
* 显示二维码
* @param deviceNo 设备编号
@ -42,4 +47,9 @@ public class TestController extends ControllerBase{
VUtils.trueThrowBusinessError(true).throwMessage("生成二维码出错");
}
}
@GetMapping("test")
public ApiResult<Boolean> test(@RequestParam Integer userId){
return ApiResult.success(ticketCallService.isInCall(userId));
}
}

View File

@ -54,7 +54,6 @@ import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
@ -131,11 +130,11 @@ public class TicketController extends ControllerBase {
@Resource
private UniPushService uniPushService;
// @Resource
// private ITicketCallService ticketCallService;
//
// @Resource
// private ITicketCallJoinService ticketCallJoinService;
@Resource
private ITicketCallService ticketCallService;
@Resource
private ITicketCallJoinService ticketCallJoinService;
/**
* 获取问题类型
@ -1235,7 +1234,7 @@ public class TicketController extends ControllerBase {
Integer handlerUserId = Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).findFirst().get();
VUtils.trueThrowBusinessError(!Objects.equals(AdminUserUtil.getUserId(), handlerUserId))
.throwMessage("不是工单主负责人无权限呼叫");
// VUtils.trueThrowBusinessError(ticketCallService.isInCall(ticket.getUserId())).throwMessage("对方正在通话中");
VUtils.trueThrowBusinessError(ticketCallService.isInCall(ticket.getUserId())).throwMessage("对方正在通话中");
AdminUser adminUser = adminUserService.getById(handlerUserId);
uniPushService.send(new UniPushMessage()
.setSenderId("admin-uid-" + handlerUserId)
@ -1248,13 +1247,14 @@ public class TicketController extends ControllerBase {
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("call")
.setCategory("ticketCall")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallToApp(adminUser, ticket.getUserId(), ticketId);
// ticketCallService.add(ticketId, handlerUserId, ticket.getUserId(), Constant.FROM_ADMIN);
ticketCallService.add(ticketId, handlerUserId, ticket.getUserId(), Constant.FROM_ADMIN);
ticketEventPublisher.publishTicketCallBeginEvent(ticketId, adminUser.getUserName());
return ApiResult.success();
}
@ -1266,34 +1266,32 @@ public class TicketController extends ControllerBase {
@PostMapping("addCallUser")
public ApiResult<Void> addCallUser(@Valid @RequestBody CallUserAddRequest request){
AdminUser adminUser = adminUserService.getById(AdminUserUtil.getUserId());
// TicketCall ticketCall = ticketCallService.lambdaQuery()
// .eq(TicketCall::getTicketId, request.getTicketId())
// .eq(TicketCall::getState, 1)
// .one();
// VUtils.trueThrowBusinessError(Objects.isNull(ticketCall)).throwMessage("未在通话中");
TicketCall ticketCall = ticketCallService.lambdaQuery()
.eq(TicketCall::getTicketId, request.getTicketId())
.eq(TicketCall::getState, 1)
.one();
VUtils.trueThrowBusinessError(Objects.isNull(ticketCall)).throwMessage("未在通话中");
request.getUserIds().forEach(userId->{
AdminUser adminUser1 = adminUserService.getById(userId);
if (Objects.nonNull(adminUser1)) {
CompletableFuture.runAsync(()->{
uniPushService.send(new UniPushMessage()
.setSenderId("admin-uid-" + adminUser.getId())
.setReceiverId("admin-uid-" + userId)
.setSendData(new UniPushMessageBody()
.setTitle("视频通话")
.setContent(adminUser.getUserName() + "请求与您视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("call")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallToAdmin(adminUser, userId, request.getTicketId());
// ticketCallJoinService.add(ticketCall.getId(), userId, Constant.FROM_ADMIN);
});
uniPushService.send(new UniPushMessage()
.setSenderId("admin-uid-" + adminUser.getId())
.setReceiverId("admin-uid-" + userId)
.setSendData(new UniPushMessageBody()
.setTitle("视频通话")
.setContent(adminUser.getUserName() + "请求与您视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("ticketCall")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallToAdmin(adminUser, userId, request.getTicketId());
ticketCallJoinService.add(ticketCall.getId(), userId, Constant.FROM_ADMIN);
}
});
return ApiResult.success();
@ -1309,9 +1307,9 @@ public class TicketController extends ControllerBase {
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在");
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()))
.throwMessage("当前工单状态不允许请求通话");
// VUtils.trueThrowBusinessError(ticketCallService.isInCall(AdminUserUtil.getUserId()))
// .throwMessage("您已加入别的通话中");
// ticketCallJoinService.join(ticketId, AdminUserUtil.getUserId(),Constant.FROM_ADMIN);
VUtils.trueThrowBusinessError(ticketCallService.isInCall(AdminUserUtil.getUserId()))
.throwMessage("您已加入别的通话中");
ticketCallJoinService.join(ticketId, AdminUserUtil.getUserId(),Constant.FROM_ADMIN);
return ApiResult.success();
}
@ -1321,10 +1319,11 @@ public class TicketController extends ControllerBase {
*/
@PostMapping("call/hangUp")
public ApiResult<Void> hangUp(@Valid @RequestBody TicketCallHangUpRequest request) {
// TicketCall ticketCall = ticketCallService.lambdaQuery()
// .eq(TicketCall::getTicketId, request.getTicketId())
// .ne(TicketCall::getState, 2)
// .one();
TicketCall ticketCall = ticketCallService.lambdaQuery()
.eq(TicketCall::getTicketId, request.getTicketId())
.ne(TicketCall::getState, 2)
.one();
boolean flag=false;
if (request.getReject()) {
AdminUser adminUser = adminUserService.getById(AdminUserUtil.getUserId());
if (StrUtil.equals(request.getFrom(), "app")) {
@ -1339,39 +1338,65 @@ public class TicketController extends ControllerBase {
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("callHangUp")
.setCategory("ticketCallHangUp")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallHangUpToApp(request.getTicketId(), request.getFromUserId(), adminUser);
// ticketCallService.hangUp(request.getTicketId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, true);
flag=ticketCallJoinService.hangUp(request.getTicketId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, true);
}else if (StrUtil.equals(request.getFrom(), "admin")) {
uniPushService.send(new UniPushMessage()
.setSenderId("admin-uid-" + adminUser.getId())
.setReceiverId("admin-uid-" + request.getFromUserId())
.setSendData(new UniPushMessageBody()
.setTitle("拒绝视频通话")
.setContent(adminUser.getUserName() + "拒绝与您视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("callHangUp")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallHangUpToAdmin(request.getTicketId(), request.getFromUserId(), adminUser);
// ticketCallJoinService.hangUp(ticketCall.getId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, true);
if (Objects.equals(request.getFromUserId(), AdminUserUtil.getUserId())){
Ticket ticket = ticketService.getById(request.getTicketId());
int handlerId= Integer.parseInt(StrUtil.split(ticket.getHandle(), ",").stream().findFirst().get());
uniPushService.send(new UniPushMessage()
.setSenderId("admin-uid-" + adminUser.getId())
.setReceiverId("admin-uid-" + handlerId)
.setSendData(new UniPushMessageBody()
.setTitle("挂断视频通话")
.setContent(adminUser.getUserName() + "挂断了与您的视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("ticketCallCancel")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallCancelToAdmin(request.getTicketId(), handlerId, adminUser);
flag=ticketCallService.hangUp(request.getTicketId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, true);
}else {
uniPushService.send(new UniPushMessage()
.setSenderId("admin-uid-" + adminUser.getId())
.setReceiverId("admin-uid-" + request.getFromUserId())
.setSendData(new UniPushMessageBody()
.setTitle("拒绝视频通话")
.setContent(adminUser.getUserName() + "拒绝与您视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(adminUser.getId())
.setUserName(adminUser.getUserName())
.setUserAvatar(adminUser.getAvatar())
.setCategory("ticketCallHangUp")
.setFrom("admin")
)
)
);
ssePushService.sendTicketCallHangUpToAdmin(request.getTicketId(), request.getFromUserId(), adminUser);
flag=ticketCallJoinService.hangUp(ticketCall.getId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, true);
}
}
}else {
// if (StrUtil.equals(request.getFrom(), "app")) {
// ticketCallService.hangUp(request.getTicketId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, false);
// }else {
// ticketCallJoinService.hangUp(ticketCall.getId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, false);
// }
if (StrUtil.equals(request.getFrom(), "app") || Objects.equals(request.getFromUserId(), AdminUserUtil.getUserId())) {
flag=ticketCallService.hangUp(request.getTicketId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, false);
}else {
flag=ticketCallJoinService.hangUp(ticketCall.getId(), AdminUserUtil.getUserId(), Constant.FROM_ADMIN, false);
}
}
if (flag){
ticketEventPublisher.publishTicketCallEndEvent(request.getTicketId());
}
return ApiResult.success();
}

View File

@ -0,0 +1,48 @@
package com.nflg.mobilebroken.admin.event;
import com.nflg.mobilebroken.admin.service.SsePushService;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import com.nflg.mobilebroken.repository.service.TicketChatService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import java.time.Instant;
public class TicketCallBeginEvent extends ApplicationEvent implements ApplicationContextAware {
private final Integer ticketId;
private final String userName;
private SsePushService ssePushService;
private TicketChatService ticketChatService;
public TicketCallBeginEvent(Object source, Integer ticketId, String userName) {
super(source);
this.ticketId = ticketId;
this.userName = userName;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ssePushService = applicationContext.getBean(SsePushService.class);
this.ticketChatService = applicationContext.getBean(TicketChatService.class);
}
public void send(){
ChatMessageDTO message = new ChatMessageDTO()
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
.setFrom("call")
.setTicketState(TicketState.Processing.getState())
.setSenderId(0)
.setSenderName("通话助手")
.setContent(userName+"发起了视频通话")
.setCreateTime(Instant.now());
ticketChatService.addMessage(ticketId, message);
//推送消息
ssePushService.sendTicketMessageToAdmin(ticketId,message);
ssePushService.sendTicketMessageToApp(ticketId,message);
}
}

View File

@ -0,0 +1,46 @@
package com.nflg.mobilebroken.admin.event;
import com.nflg.mobilebroken.admin.service.SsePushService;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import com.nflg.mobilebroken.repository.service.TicketChatService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import java.time.Instant;
public class TicketCallEndEvent extends ApplicationEvent implements ApplicationContextAware {
private final Integer ticketId;
private SsePushService ssePushService;
private TicketChatService ticketChatService;
public TicketCallEndEvent(Object source, Integer ticketId) {
super(source);
this.ticketId = ticketId;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ssePushService = applicationContext.getBean(SsePushService.class);
this.ticketChatService = applicationContext.getBean(TicketChatService.class);
}
public void send(){
ChatMessageDTO message = new ChatMessageDTO()
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
.setFrom("call")
.setTicketState(TicketState.Processing.getState())
.setSenderId(0)
.setSenderName("通话助手")
.setContent("视频通话已结束")
.setCreateTime(Instant.now());
ticketChatService.addMessage(ticketId, message);
//推送消息
ssePushService.sendTicketMessageToAdmin(ticketId,message);
ssePushService.sendTicketMessageToApp(ticketId,message);
}
}

View File

@ -1,9 +1,6 @@
package com.nflg.mobilebroken.admin.listener;
import com.nflg.mobilebroken.admin.event.TicketAssignedEvent;
import com.nflg.mobilebroken.admin.event.TicketCloseEvent;
import com.nflg.mobilebroken.admin.event.TicketCompleteEvent;
import com.nflg.mobilebroken.admin.event.TicketReplyEvent;
import com.nflg.mobilebroken.admin.event.*;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@ -34,4 +31,16 @@ public class TicketEventListener {
public void handleTicketCloseEvent(TicketCloseEvent event) {
event.send();
}
@Async
@EventListener
public void handleTicketCallBeginEvent(TicketCallBeginEvent event) {
event.send();
}
@Async
@EventListener
public void handleTicketCallEndEvent(TicketCallEndEvent event) {
event.send();
}
}

View File

@ -1,9 +1,6 @@
package com.nflg.mobilebroken.admin.publisher;
import com.nflg.mobilebroken.admin.event.TicketAssignedEvent;
import com.nflg.mobilebroken.admin.event.TicketCloseEvent;
import com.nflg.mobilebroken.admin.event.TicketCompleteEvent;
import com.nflg.mobilebroken.admin.event.TicketReplyEvent;
import com.nflg.mobilebroken.admin.event.*;
import com.nflg.mobilebroken.repository.entity.Ticket;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
@ -44,4 +41,16 @@ public class TicketEventPublisher {
event.setApplicationContext(applicationContext);
eventPublisher.publishEvent(event);
}
public void publishTicketCallBeginEvent(Integer ticketId, String userName) {
TicketCallBeginEvent event = new TicketCallBeginEvent(this, ticketId,userName);
event.setApplicationContext(applicationContext);
eventPublisher.publishEvent(event);
}
public void publishTicketCallEndEvent(Integer ticketId) {
TicketCallEndEvent event = new TicketCallEndEvent(this, ticketId);
event.setApplicationContext(applicationContext);
eventPublisher.publishEvent(event);
}
}

View File

@ -37,10 +37,11 @@ public class SsePushService {
TicketMessagePushRequest request=new TicketMessagePushRequest()
.setTicketId(ticketId)
.setMessage(buildMessage(ticketId,message));
log.debug("发送SSE消息{}", JSONUtil.toJsonStr(request));
ApiResult<?> result = sendMessage(request,"admin");
log.debug("发送消息结果:{}", JSONUtil.toJsonStr(result));
log.debug("发送SSE消息结果:{}", JSONUtil.toJsonStr(result));
} catch (Exception e) {
log.error("发送消息出错", e);
log.error("发送SSE消息出错", e);
}
}
@ -111,6 +112,7 @@ public class SsePushService {
.setType("ticketMessage")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketMessage")
.setData(new ChatMessageVO()
.setId(message.getId())
.setFrom(message.getFrom())
@ -146,6 +148,7 @@ public class SsePushService {
.setType("ticketMessageWithdraw")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketMessageWithdraw")
.setData(messageId)
);
}
@ -158,6 +161,7 @@ public class SsePushService {
.setType("ticketCall")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCall")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())
@ -182,6 +186,7 @@ public class SsePushService {
.setType("ticketCall")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCall")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())
@ -211,6 +216,7 @@ public class SsePushService {
.setType("ticketCallHangUp")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCallHangUp")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())
@ -235,6 +241,32 @@ public class SsePushService {
.setType("ticketCallHangUp")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCallHangUp")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())
.setUserName(user.getUserName())
.setUserAvatar(user.getAvatar())
.setFrom("admin")
)
)
);
ApiResult<?> result = sendMessageByUser(request, "admin");
log.debug("发送消息结果:{}", JSONUtil.toJsonStr(result));
} catch (Exception e) {
log.error("发送消息出错", e);
}
}
public void sendTicketCallCancelToAdmin(@NotNull Integer ticketId, @NotNull Integer userId, AdminUser user) {
try {
PushUserMessageRequest request = new PushUserMessageRequest()
.setUserId(userId)
.setMessage(new PushMessageDTO()
.setType("ticketCallCancel")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCallCancel")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())

View File

@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.nflg.mobilebroken.cfs.publisher.TicketEventPublisher;
import com.nflg.mobilebroken.cfs.service.SsePushService;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
@ -92,11 +93,11 @@ public class TicketController extends ControllerBase {
@Resource
private UniPushService uniPushService;
// @Resource
// private ITicketCallService ticketCallService;
//
// @Resource
// private ITicketCallJoinService ticketCallJoinService;
@Resource
private ITicketCallService ticketCallService;
@Resource
private ITicketCallJoinService ticketCallJoinService;
/**
* 搜索设备
@ -489,7 +490,7 @@ public class TicketController extends ControllerBase {
VUtils.trueThrowBusinessError(!Objects.equals(AppUserUtil.getUserId(), ticket.getUserId()))
.throwMessage("不是工单创建人无权限呼叫");
Integer handlerUserId = Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).findFirst().get();
// VUtils.trueThrowBusinessError(ticketCallService.isInCall(handlerUserId)).throwMessage("对方正在通话中");
VUtils.trueThrowBusinessError(ticketCallService.isInCall(handlerUserId)).throwMessage("对方正在通话中");
AppUser appUser = appUserService.getById(ticket.getUserId());
uniPushService.send(new UniPushMessage()
.setSenderId("app-uid-" + ticket.getUserId())
@ -502,13 +503,14 @@ public class TicketController extends ControllerBase {
.setUserId(appUser.getId())
.setUserName(appUser.getName())
.setUserAvatar(appUser.getAvatar())
.setCategory("call")
.setCategory("ticketCall")
.setFrom("app")
)
)
);
ssePushService.sendTicketCallToAdmin(appUser, handlerUserId, ticketId);
// ticketCallService.add(ticketId, AppUserUtil.getUserId(), handlerUserId, Constant.FROM_APP);
ticketCallService.add(ticketId, AppUserUtil.getUserId(), handlerUserId, Constant.FROM_APP);
ticketEventPublisher.publishTicketCallBeginEvent(ticketId,appUser.getName());
return ApiResult.success();
}
@ -522,9 +524,9 @@ public class TicketController extends ControllerBase {
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在");
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()))
.throwMessage("当前工单状态不允许通话");
// VUtils.trueThrowBusinessError(ticketCallService.isInCall(AppUserUtil.getUserId()))
// .throwMessage("您已加入别的通话中");
// ticketCallJoinService.join(ticketId, AppUserUtil.getUserId(),Constant.FROM_APP);
VUtils.trueThrowBusinessError(ticketCallService.isInCall(AppUserUtil.getUserId()))
.throwMessage("您已加入别的通话中");
ticketCallJoinService.join(ticketId, AppUserUtil.getUserId(),Constant.FROM_APP);
return ApiResult.success();
}
@ -534,26 +536,54 @@ public class TicketController extends ControllerBase {
*/
@PostMapping("call/hangUp")
public ApiResult<Void> hangUp(@Valid @RequestBody TicketCallHangUpRequest request) {
boolean flag=false;
if (request.getReject()) {
AppUser appUser = appUserService.getById(AppUserUtil.getUserId());
uniPushService.send(new UniPushMessage()
.setSenderId("app-uid-" + appUser.getId())
.setReceiverId("admin-uid-" + request.getFromUserId())
.setSendData(new UniPushMessageBody()
.setTitle("拒绝视频通话")
.setContent(appUser.getName() + "拒绝与您视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(appUser.getId())
.setUserName(appUser.getName())
.setUserAvatar(appUser.getAvatar())
.setCategory("callHangUp")
.setFrom("app")
)
)
);
ssePushService.sendTicketCallHangUpToAdmin(request.getTicketId(), request.getFromUserId(), appUser);
// ticketCallService.hangUp(request.getTicketId(), AppUserUtil.getUserId(), Constant.FROM_APP, true);
if (StrUtil.equals(request.getFrom(), Constant.FROM_APP) && Objects.equals(AppUserUtil.getUserId(), request.getFromUserId())) {
AppUser appUser = appUserService.getById(AppUserUtil.getUserId());
Ticket ticket = ticketService.getById(request.getTicketId());
int handlerId= Integer.parseInt(StrUtil.split(ticket.getHandle(), ",").stream().findFirst().get());
uniPushService.send(new UniPushMessage()
.setSenderId("app-uid-" + appUser.getId())
.setReceiverId("admin-uid-" + handlerId)
.setSendData(new UniPushMessageBody()
.setTitle("挂断视频通话")
.setContent(appUser.getName() + "挂断了与您的视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(appUser.getId())
.setUserName(appUser.getName())
.setUserAvatar(appUser.getAvatar())
.setCategory("ticketCallCancel")
.setFrom("app")
)
)
);
ssePushService.sendTicketCallCancelToAdmin(request.getTicketId(), handlerId, appUser);
flag=ticketCallService.hangUp(request.getTicketId(), AppUserUtil.getUserId(), Constant.FROM_APP, true);
}else {
AppUser appUser = appUserService.getById(AppUserUtil.getUserId());
uniPushService.send(new UniPushMessage()
.setSenderId("app-uid-" + appUser.getId())
.setReceiverId("admin-uid-" + request.getFromUserId())
.setSendData(new UniPushMessageBody()
.setTitle("拒绝视频通话")
.setContent(appUser.getName() + "拒绝与您视频通话")
.setPayload(new UniPushMessageCallPayload()
.setTicketId(request.getTicketId())
.setUserId(appUser.getId())
.setUserName(appUser.getName())
.setUserAvatar(appUser.getAvatar())
.setCategory("ticketCallHangUp")
.setFrom("app")
)
)
);
ssePushService.sendTicketCallHangUpToAdmin(request.getTicketId(), request.getFromUserId(), appUser);
flag=ticketCallJoinService.hangUp(request.getTicketId(), AppUserUtil.getUserId(), Constant.FROM_APP, true);
}
}
if (flag){
ticketEventPublisher.publishTicketCallEndEvent(request.getTicketId());
}
return ApiResult.success();
}

View File

@ -0,0 +1,48 @@
package com.nflg.mobilebroken.cfs.event;
import com.nflg.mobilebroken.cfs.service.SsePushService;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import com.nflg.mobilebroken.repository.service.TicketChatService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import java.time.Instant;
public class TicketCallBeginEvent extends ApplicationEvent implements ApplicationContextAware {
private final Integer ticketId;
private final String userName;
private SsePushService ssePushService;
private TicketChatService ticketChatService;
public TicketCallBeginEvent(Object source, Integer ticketId, String userName) {
super(source);
this.ticketId = ticketId;
this.userName = userName;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ssePushService = applicationContext.getBean(SsePushService.class);
this.ticketChatService = applicationContext.getBean(TicketChatService.class);
}
public void send(){
ChatMessageDTO message = new ChatMessageDTO()
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
.setFrom("call")
.setTicketState(TicketState.Processing.getState())
.setSenderId(0)
.setSenderName("通话助手")
.setContent(userName+"发起了视频通话")
.setCreateTime(Instant.now());
ticketChatService.addMessage(ticketId, message);
//推送消息
ssePushService.sendTicketMessageToAdmin(ticketId,message);
ssePushService.sendTicketMessageToApp(ticketId,message);
}
}

View File

@ -0,0 +1,46 @@
package com.nflg.mobilebroken.cfs.event;
import com.nflg.mobilebroken.cfs.service.SsePushService;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import com.nflg.mobilebroken.repository.service.TicketChatService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import java.time.Instant;
public class TicketCallEndEvent extends ApplicationEvent implements ApplicationContextAware {
private final Integer ticketId;
private SsePushService ssePushService;
private TicketChatService ticketChatService;
public TicketCallEndEvent(Object source,Integer ticketId) {
super(source);
this.ticketId = ticketId;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ssePushService = applicationContext.getBean(SsePushService.class);
this.ticketChatService = applicationContext.getBean(TicketChatService.class);
}
public void send(){
ChatMessageDTO message = new ChatMessageDTO()
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
.setFrom("call")
.setTicketState(TicketState.Processing.getState())
.setSenderId(0)
.setSenderName("通话助手")
.setContent("视频通话已结束")
.setCreateTime(Instant.now());
ticketChatService.addMessage(ticketId, message);
//推送消息
ssePushService.sendTicketMessageToAdmin(ticketId,message);
ssePushService.sendTicketMessageToApp(ticketId,message);
}
}

View File

@ -37,4 +37,16 @@ public class TicketEventListener {
public void handleTicketCloseEvent(TicketCloseEvent event) {
event.send();
}
@Async
@EventListener
public void handleTicketCallBeginEvent(TicketCallBeginEvent event) {
event.send();
}
@Async
@EventListener
public void handleTicketCallEndEvent(TicketCallEndEvent event) {
event.send();
}
}

View File

@ -52,4 +52,16 @@ public class TicketEventPublisher {
event.setApplicationContext(applicationContext);
eventPublisher.publishEvent(event);
}
public void publishTicketCallBeginEvent(Integer ticketId, String userName) {
TicketCallBeginEvent event = new TicketCallBeginEvent(this, ticketId,userName);
event.setApplicationContext(applicationContext);
eventPublisher.publishEvent(event);
}
public void publishTicketCallEndEvent(Integer ticketId) {
TicketCallEndEvent event = new TicketCallEndEvent(this, ticketId);
event.setApplicationContext(applicationContext);
eventPublisher.publishEvent(event);
}
}

View File

@ -103,6 +103,7 @@ public class SsePushService {
.setType("ticketMessage")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketMessage")
.setData(new ChatMessageVO()
.setId(message.getId())
.setFrom(message.getFrom())
@ -136,7 +137,10 @@ public class SsePushService {
private PushMessageDTO buildWithdrawMessage(Integer ticketId,String messageId) {
return new PushMessageDTO()
.setType("ticketMessageWithdraw")
.setData(new PushMessageDataBody().setTargetId(ticketId).setData(messageId));
.setData(new PushMessageDataBody()
.setType("ticketMessageWithdraw")
.setTargetId(ticketId)
.setData(messageId));
}
public void sendTicketCallToAdmin(AppUser appUser, Integer userId, Integer ticketId) {
@ -146,6 +150,7 @@ public class SsePushService {
.setType("ticketCall")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCall")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(appUser.getId())
@ -176,6 +181,32 @@ public class SsePushService {
.setType("ticketCallHangUp")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCallHangUp")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())
.setUserName(user.getName())
.setUserAvatar(user.getAvatar())
.setFrom("app")
)
)
);
ApiResult<?> result = sendMessageByUser(request, "admin");
log.debug("发送消息结果:{}", JSONUtil.toJsonStr(result));
} catch (Exception e) {
log.error("发送消息出错", e);
}
}
public void sendTicketCallCancelToAdmin(@NotNull Integer ticketId, @NotNull Integer userId, AppUser user) {
try {
PushUserMessageRequest request = new PushUserMessageRequest()
.setUserId(userId)
.setMessage(new PushMessageDTO()
.setType("ticketCallCancel")
.setData(new PushMessageDataBody()
.setTargetId(ticketId)
.setType("ticketCallCancel")
.setData(new UniPushMessageCallPayload()
.setTicketId(ticketId)
.setUserId(user.getId())

View File

@ -9,5 +9,10 @@ public class PushMessageDataBody {
private Integer targetId;
/**
* 消息类型
*/
private String type;
private Object data;
}

View File

@ -12,6 +12,8 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@Accessors(chain = true)
public class UserSseEmitter extends SseEmitter {
private String from;
private Integer userId;
private Integer ticketId;
@ -19,4 +21,8 @@ public class UserSseEmitter extends SseEmitter {
public UserSseEmitter(){
super(0L);
}
public String getUser(){
return from + "-" + userId;
}
}

View File

@ -1,25 +0,0 @@
package com.nflg.mobilebroken.push.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径
.allowedOrigins("*") // 允许所有来源
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的HTTP方法
.allowedHeaders("*") // 允许所有请求头
.allowCredentials(true) // 允许携带凭证如cookies
.maxAge(3600); // 预检请求的缓存时间
}
};
}
}

View File

@ -6,9 +6,11 @@ import com.nflg.mobilebroken.common.pojo.request.PushUserMessageRequest;
import com.nflg.mobilebroken.common.pojo.request.TicketMessagePushRequest;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.AppUserUtil;
import com.nflg.mobilebroken.common.util.IdUtil;
import com.nflg.mobilebroken.push.service.impl.APPSSEManagerService;
import com.nflg.mobilebroken.push.service.impl.AdminSSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@ -44,11 +46,14 @@ public class SSEController {
@PostMapping("app/push/ticket/message")
public ApiResult<Void> pushToApp(@Valid @RequestBody @NotNull TicketMessagePushRequest request){
try {
MDC.put("traceId", IdUtil.getIdStr());
appsseManagerService.sendTicketMessage(request.getTicketId(),request.getMessage());
return ApiResult.success();
} catch (IOException e) {
log.error("发送SSE消息出错", e);
return ApiResult.error(STATE.BusinessError,e.getMessage());
}finally {
MDC.remove("traceId");
}
}
@ -59,11 +64,14 @@ public class SSEController {
@PostMapping("app/push/user/message")
public ApiResult<Void> appMessageByUser(@Valid @RequestBody @NotNull PushUserMessageRequest request){
try {
MDC.put("traceId", IdUtil.getIdStr());
appsseManagerService.sendByUser(request.getUserId(),request.getMessage());
return ApiResult.success();
} catch (Exception e) {
log.error("发送SSE消息出错", e);
return ApiResult.error(STATE.BusinessError,e.getMessage());
}finally {
MDC.remove("traceId");
}
}
@ -82,11 +90,14 @@ public class SSEController {
@PostMapping("admin/push/ticket/message")
public ApiResult<Void> adminPushTicketMessage(@Valid @RequestBody @NotNull TicketMessagePushRequest request){
try {
MDC.put("traceId", IdUtil.getIdStr());
adminSSEManagerService.sendTicketMessage(request.getTicketId(),request.getMessage());
return ApiResult.success();
} catch (IOException e) {
log.error("发送SSE消息出错", e);
return ApiResult.error(STATE.BusinessError,e.getMessage());
}finally {
MDC.remove("traceId");
}
}
@ -97,11 +108,14 @@ public class SSEController {
@PostMapping("admin/push/user/message")
public ApiResult<Void> adminMessageByUser(@Valid @RequestBody @NotNull PushUserMessageRequest request){
try {
MDC.put("traceId", IdUtil.getIdStr());
adminSSEManagerService.sendByUser(request.getUserId(),request.getMessage());
return ApiResult.success();
} catch (Exception e) {
log.error("发送SSE消息出错", e);
return ApiResult.error(STATE.BusinessError,e.getMessage());
}finally {
MDC.remove("traceId");
}
}
}

View File

@ -57,30 +57,30 @@ public class SSEManagerBase {
protected SseEmitter connect(Integer ticketId,Integer userId) {
check();
log.info(from+"SSE连接:用户id:"+userId+",工单id:"+ticketId);
UserSseEmitter emitter = new UserSseEmitter(userId,ticketId);
log.info(from + "SSE连接:用户id:" + userId + ",工单id:" + ticketId);
UserSseEmitter emitter = new UserSseEmitter(from, userId, ticketId);
SSE_EMITTERS.add(emitter);
ScheduledFuture<?> heartbeatTask = startHeartbeat(emitter);
emitter.onError((ex) -> {
remove(userId, emitter,heartbeatTask);
log.error("SSE异常:"+userId, ex);
remove(emitter,heartbeatTask);
log.error("SSE异常({}):{}", ex.getMessage(),emitter.getUser());
});
emitter.onTimeout(() -> {
remove(userId, emitter,heartbeatTask);
remove(emitter,heartbeatTask);
log.error("SSE超时:"+userId);
});
emitter.onCompletion(() -> {
remove(userId, emitter,heartbeatTask);
remove(emitter,heartbeatTask);
log.error("SSE完成:"+userId);
});
try {
emitter.send(SseEmitter.event().data("已连接").reconnectTime(5000));
}catch (ClientAbortException e){
log.error("客户端断开连接:{}", userId);
emitter.complete();
emitter.completeWithError(e);
}
catch (IOException e) {
log.error("sse发送数据出错", e);
log.error("sse发送数据出错:{}", e.getMessage());
emitter.completeWithError(e);
}
return emitter;
@ -99,10 +99,10 @@ public class SSEManagerBase {
try {
emitter.send(SseEmitter.event().name(dto.getType()).data(dto.getData()));
} catch (ClientAbortException e) {
log.error("客户端断开连接:{}", emitter.getUserId());
emitter.complete();
log.error("客户端断开连接:{}", emitter.getUser());
emitter.completeWithError(e);
} catch (IOException e) {
log.error("sse发送数据出错", e);
log.error("sse发送数据出错:{}", e.getMessage());
emitter.completeWithError(e);
}
});
@ -111,7 +111,7 @@ public class SSEManagerBase {
protected void sendByUser(Integer userId, PushMessageDTO dto) {
log.info(StrUtil.format(from + "SSE发送消息,用户id: {},内容: {}", userId, dto));
List<UserSseEmitter> emitters = SSE_EMITTERS.stream()
.filter(s -> Objects.equals(s.getUserId(), userId))
.filter(s -> StrUtil.equals(s.getFrom(), from) && Objects.equals(s.getUserId(), userId))
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(emitters)) {
log.info(StrUtil.format(from + "用户未连接:{}", userId));
@ -122,26 +122,30 @@ public class SSEManagerBase {
emitter.send(SseEmitter.event().name(dto.getType()).data(dto.getData()));
log.info("发送成功");
} catch (ClientAbortException e) {
log.error("客户端断开连接:{}", emitter.getUserId());
emitter.complete();
log.error("客户端断开连接:{}", emitter.getUser());
emitter.completeWithError(e);
}catch (IOException e) {
log.error("sse发送数据出错", e);
log.error("sse发送数据出错:{}", e.getMessage());
emitter.completeWithError(e);
}
});
}
private void remove(Integer userId,UserSseEmitter emitter,ScheduledFuture<?> heartbeatTask){
heartbeatTask.cancel(false);
private void remove(UserSseEmitter emitter,ScheduledFuture<?> heartbeatTask){
heartbeatTask.cancel(true);
SSE_EMITTERS.remove(emitter);
emitter.complete();
emitter=null;
}
private ScheduledFuture<?> startHeartbeat(UserSseEmitter emitter) {
return taskScheduler.scheduleAtFixedRate(() -> {
try {
emitter.send(SseEmitter.event().data("ping"));
if (Objects.nonNull(emitter)) {
emitter.send(SseEmitter.event().data("ping"));
}
} catch (IOException e) {
log.error("sse发送ping数据出错({}):{}", emitter.getUser(),e.getMessage());
emitter.completeWithError(e);
}
}, 30_000);

View File

@ -22,7 +22,7 @@ public interface ITicketCallJoinService extends IService<TicketCallJoin> {
boolean allIsHangUp(Integer callId);
void hangUp(Integer callId, Integer userId, String from, boolean reject);
boolean hangUp(Integer callId, Integer userId, String from, boolean reject);
void add(Integer callId, Integer userId, String from);

View File

@ -19,5 +19,5 @@ public interface ITicketCallService extends IService<TicketCall> {
void add(Integer ticketId, Integer callerUserId, Integer calledUserId, String from);
void hangUp(@NotNull Integer ticketId, Integer userId, String from, boolean reject);
boolean hangUp(@NotNull Integer ticketId, Integer userId, String from, boolean reject);
}

View File

@ -42,7 +42,7 @@ public class TicketCallJoinServiceImpl extends ServiceImpl<TicketCallJoinMapper,
.eq(TicketCall::getTicketId, ticketId)
.ne(TicketCall::getState, 2)
.one();
VUtils.trueThrowBusinessError(Objects.isNull(ticketCall)).throwMessage("加入失败");
VUtils.trueThrowBusinessError(Objects.isNull(ticketCall)).throwMessage("加入失败,通话已结束");
TicketCallJoin ticketCallJoin = lambdaQuery()
.eq(TicketCallJoin::getCallId, ticketCall.getId())
.eq(TicketCallJoin::getUserId, userId)
@ -66,13 +66,14 @@ public class TicketCallJoinServiceImpl extends ServiceImpl<TicketCallJoinMapper,
@Transactional
@Override
public void hangUp(Integer callId, Integer userId, String from, boolean reject) {
public boolean hangUp(Integer callId, Integer userId, String from, boolean reject) {
TicketCallJoin ticketCallJoin = lambdaQuery()
.eq(TicketCallJoin::getCallId, callId)
.ne(TicketCallJoin::getState, 2)
.eq(TicketCallJoin::getUserId, userId)
.eq(TicketCallJoin::getFrom, from)
.one();
boolean flag = false;
if (Objects.nonNull(ticketCallJoin)) {
ticketCallJoin.setState(2);
if (!reject) {
@ -96,8 +97,10 @@ public class TicketCallJoinServiceImpl extends ServiceImpl<TicketCallJoinMapper,
.set(!reject,TicketCall::getHangupTime, LocalDateTime.now())
.eq(TicketCall::getId, callId)
.update();
flag = true;
}
}
return flag;
}
@Override
@ -113,6 +116,7 @@ public class TicketCallJoinServiceImpl extends ServiceImpl<TicketCallJoinMapper,
.setUserId(userId)
.setFrom(from)
.setState(0)
.setCreateTime(LocalDateTime.now())
);
}
}

View File

@ -59,11 +59,12 @@ public class TicketCallServiceImpl extends ServiceImpl<TicketCallMapper, TicketC
}
@Override
public void hangUp(Integer ticketId, Integer userId, String from, boolean reject) {
public boolean hangUp(Integer ticketId, Integer userId, String from, boolean reject) {
TicketCall ticketCall = lambdaQuery()
.eq(TicketCall::getTicketId, ticketId)
.ne(TicketCall::getState, 2)
.one();
boolean flag = false;
if (Objects.nonNull(ticketCall)){
if ((Objects.equals(ticketCall.getCallerUserId(), userId) && StrUtil.equals(ticketCall.getFrom(), Constant.FROM_APP))
|| ticketCallJoinService.allIsHangUp(ticketCall.getId())){
@ -74,7 +75,8 @@ public class TicketCallServiceImpl extends ServiceImpl<TicketCallMapper, TicketC
}
updateById(ticketCall);
}
ticketCallJoinService.hangUp(ticketCall.getId(), userId, from, reject);
flag=ticketCallJoinService.hangUp(ticketCall.getId(), userId, from, reject);
}
return flag;
}
}

View File

@ -2,10 +2,11 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.mobilebroken.repository.mapper.TicketCallJoinMapper">
<select id="isInCall" resultType="boolean">
select exists(select 1
from ticket_call tc
left join ticket_call_join tcj on tc.id = tcj.call_id
where tc.state = 1
and tcj.user_id = #{userId})
SELECT COUNT(*) > 0
FROM ticket_call tc
INNER JOIN ticket_call_join tcj ON tc.id = tcj.call_id
WHERE tc.state = 1
AND tcj.state = 1
AND tcj.user_id = #{userId}
</select>
</mapper>

View File

@ -1,25 +0,0 @@
package com.nflg.mobilebroken.starter.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径
.allowedOrigins("*") // 允许所有来源
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的HTTP方法
.allowedHeaders("*") // 允许所有请求头
.allowCredentials(true) // 允许携带凭证如cookies
.maxAge(3600); // 预检请求的缓存时间
}
};
}
}

View File

@ -43,6 +43,9 @@ public class RedisConfig {
template.setKeySerializer(new StringRedisSerializer());
// 设置 Value 的序列化器
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 设置 Hash Key 的序列化器
template.setHashKeySerializer(new StringRedisSerializer());
// 设置 Hash Value 的序列化器
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}