Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
luolm 2025-03-07 20:51:11 +08:00
commit 804cf10a29
34 changed files with 241 additions and 494 deletions

View File

@ -89,7 +89,7 @@
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version>
<version>9.3.1</version>
</dependency>
<!-- iText (required by Flying Saucer) -->
<dependency>

View File

@ -13,6 +13,7 @@ import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.*;
import com.nflg.mobilebroken.common.pojo.vo.*;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.AppUser;
import com.nflg.mobilebroken.repository.entity.AppUserApplyfor;
@ -195,6 +196,7 @@ public class AppUserController extends ControllerBase {
.setAreaId(request.getAreaId())
.setTitleId(request.getTitleId())
.setCompanyId(StrUtil.join(",", request.getCompanyIds()))
.setUpdateBy(AdminUserUtil.getUserName())
.setUpdateTime(LocalDateTime.now());
if (!Objects.equals(user.getState(), UserState.ToBeActivated.getState()) && Objects.nonNull(request.getEnable())) {
user.setState(request.getEnable() ? UserState.Activated.getState() : UserState.Disabled.getState());
@ -248,9 +250,9 @@ public class AppUserController extends ControllerBase {
.setSalesUserName(request.getSalesUserName())
.setPhone(request.getPhone())
.setLanguageCode(request.getLanguageCode())
.setAreaId(request.getAreaId())
.setTitleId(request.getTitleId())
.setCompanyId(StrUtil.join(",", request.getCompanyIds()))
.setUpdateBy(AdminUserUtil.getUserName())
.setUpdateTime(LocalDateTime.now());
if (!Objects.equals(user.getState(), UserState.ToBeActivated.getState()) && Objects.nonNull(request.getEnable())) {
user.setState(request.getEnable() ? UserState.Activated.getState() : UserState.Disabled.getState());

View File

@ -108,7 +108,9 @@ public class DeviceComponentController extends ControllerBase {
public ApiResult<Boolean> setPart(@Valid @RequestBody DeviceComponentDTO component){
if(CollUtil.isEmpty(component.getComponent())){
throw new NflgException(STATE.ParamErr,"机型部件不能为空");
//清空机型部件
deviceComponentDetailService.delByComponentId(component.getId());
return ApiResult.success(true);
}
DeviceComponent ent = Convert.convert(DeviceComponent.class, component);
List<String> compinets = component.getComponent().stream().map(u -> u.getPartName()).collect(Collectors.toList());

View File

@ -1,34 +0,0 @@
package com.nflg.mobilebroken.admin.controller;
import com.nflg.mobilebroken.admin.annotation.ApiMark;
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
@RestController
@Slf4j
@RequestMapping("/sse")
public class SSEController extends ControllerBase {
@Resource
private APPSSEManagerService sseManagerService;
/**
* 建立sse连接
*
* @param userId 用户id
*/
@GetMapping(value = "connect", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ApiMark(moduleName = "连接", apiName = "SSE", isPublic = true)
public SseEmitter connect(@RequestParam String userId) {
return sseManagerService.connect(Integer.valueOf(userId));
}
}

View File

@ -78,9 +78,6 @@ public class TicketController extends ControllerBase {
@Resource
private IAppAreaService appAreaService;
@Resource
private ITBaseAreaService adminAreaService;
@Resource
private IDictionaryItemService dictionaryItemService;
@ -99,6 +96,9 @@ public class TicketController extends ControllerBase {
@Resource
private ITicketFavoritesService ticketFavoritesService;
@Resource
private ITBasePartService partService;
/**
* 获取问题类型
* @return 问题类型列表
@ -195,6 +195,16 @@ public class TicketController extends ControllerBase {
return ApiResult.success();
}
/**
* 获取所有设备部件
* @param name 部件名称模糊查询
* @return 部件列表
*/
@GetMapping("getDeviceComponents")
public ApiResult<List<String>> getDeviceComponents(@RequestParam String name){
return ApiResult.success(partService.getSimpleList(name));
}
/**
* 搜索工单
* @param request 请求参数
@ -229,7 +239,7 @@ public class TicketController extends ControllerBase {
}
}
if (CollectionUtil.isNotEmpty(item.getChildren())) {
item.getChildren().removeIf(child -> !child.getSelected());
item.getChildren().removeIf(child -> !Objects.equals(child.getSelected(),true));
}
});
vo.getServiceEvaluation().removeIf(item -> !item.getSelected());
@ -246,10 +256,10 @@ public class TicketController extends ControllerBase {
}
}
if (CollectionUtil.isNotEmpty(item.getChildren())) {
item.getChildren().removeIf(child -> !child.getSelected());
item.getChildren().removeIf(child ->!Objects.equals(child.getSelected(),true));
}
});
vo.getExperienceEvaluation().removeIf(item -> !item.getSelected());
vo.getExperienceEvaluation().removeIf(item -> !Objects.equals(item.getSelected(),true));
return new TicketEvaluateVO()
.setScore(ticketEvaluate.getScore())
.setFeedback(ticketEvaluate.getFeedback())
@ -290,6 +300,7 @@ public class TicketController extends ControllerBase {
ticketChatService.addMessage(ticket.getId(), message);
//推送消息
ssePushService.sendTicketMessageToApp(ticket.getId(),message);
ssePushService.sendTicketMessageToAdmin(ticket.getId(),message);
return ApiResult.success();
}
@ -363,6 +374,18 @@ public class TicketController extends ControllerBase {
for (Integer id : ids){
Ticket ticket=ticketService.rejectTicket(id);
// ticketEventPublisher.publishTicketCompleteEvent(ticket);
ChatMessageDTO message = new ChatMessageDTO()
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
.setFrom("system")
.setTicketState(ticket.getState())
.setSenderId(0)
.setSenderName("服务助手")
.setContent("<b>工单驳回</b><br/>工单被驳回,请继续跟进处理。")
.setCreateTime(Instant.now());
ticketChatService.addMessage(id, message);
//推送消息
ssePushService.sendTicketMessageToAdmin(id,message);
ssePushService.sendTicketMessageToApp(id,message);
}
return ApiResult.success();
}
@ -414,9 +437,9 @@ public class TicketController extends ControllerBase {
if (StrUtil.isNotBlank(ticket.getAttachments())) {
StrUtil.split(ticket.getAttachments(), ",").forEach(item -> {
if (item.endsWith(".jpg") || item.endsWith(".png") || item.endsWith(".jpeg")) {
images.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),item));
images.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),urlEncode(item)));
} else {
files.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),item));
files.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),urlEncode(item)));
}
});
}
@ -425,6 +448,24 @@ public class TicketController extends ControllerBase {
images.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),item));
});
}
//加上聊天中的图片和文件
List<ChatMessageVO> messageVOS=ticketChatService.getMessages(ticket.getId());
messageVOS.forEach(messageVO -> {
if (CollectionUtil.isNotEmpty(messageVO.getImages())){
messageVO.getImages().forEach(image -> {
images.add(new FileInfo(image.substring(image.lastIndexOf("/")+1),image));
});
}
if (CollectionUtil.isNotEmpty(messageVO.getAttachments())){
messageVO.getAttachments().forEach(attachment -> {
if (attachment.endsWith(".jpg") || attachment.endsWith(".png") || attachment.endsWith(".jpeg")) {
images.add(new FileInfo(attachment.substring(attachment.lastIndexOf("/")+1),urlEncode(attachment)));
} else {
files.add(new FileInfo(attachment.substring(attachment.lastIndexOf("/")+1),urlEncode(attachment)));
}
});
}
});
TicketPdfVO vo = new TicketPdfVO()
.setNo(ticket.getNo())
.setTitle(ticket.getTitle())
@ -476,7 +517,7 @@ public class TicketController extends ControllerBase {
// renderer.layout();
// renderer.createPDF(response.getOutputStream());
ITextRenderer renderer = new ITextRenderer();
BaseFont baseFont = BaseFont.createFont("fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
// BaseFont baseFont = BaseFont.createFont("fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
renderer.getFontResolver().addFont("fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
renderer.setDocumentFromString(html);
renderer.layout();
@ -490,6 +531,13 @@ public class TicketController extends ControllerBase {
}
}
private String urlEncode(String url){
int index = url.lastIndexOf("/");
String pre= url.substring(0,index+1);
String end = url.substring(index+1);
return pre+URLEncoder.encode(end, StandardCharsets.UTF_8);
}
/**
* 获取工单详情
* @param id 工单编号
@ -499,10 +547,10 @@ public class TicketController extends ControllerBase {
public ApiResult<TicketInfoVO> getTicket(@Valid @RequestParam @NotNull Integer id) {
Ticket ticket = ticketService.getById(id);
AppUser user = appUserService.getById(ticket.getUserId());
String areaName;
String areaName = "";
if (user.getIsPrimary()){
areaName=adminAreaService.getById(user.getAreaId()).getAreaName();
}else {
areaName=StrUtil.join(",",customerService.getAreas(Arrays.stream(user.getCompanyId().split(",")).map(Integer::parseInt).collect(Collectors.toList())));
}else if (Objects.nonNull(user.getAreaId())){
areaName = appAreaService.getById(user.getAreaId()).getName();
}
// TBaseCustomer company = customerService.getById(Integer.valueOf(user.getCompanyId()));

View File

@ -23,6 +23,5 @@ public class DeviceComponentDTO {
/**
* 机型部件-多个以逗号隔开
*/
@NotEmpty(message = "机型部件不能为空")
private List<DeviceComponentDetailDTO> component;
}

View File

@ -1,43 +0,0 @@
package com.nflg.mobilebroken.admin.service.impl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.dto.UserDTO;
import com.nflg.mobilebroken.starter.service.INotifyPushService;
import com.nflg.mobilebroken.starter.service.SSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Objects;
@Service
@Slf4j
public class SSEINotifyPushService implements INotifyPushService {
@Resource
@Qualifier("APPSSEManagerService")
private SSEManagerService sseManagerService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Override
public void push(UserDTO user, String subject, String content) {
// try {
// SSEMessageDTO message = new SSEMessageDTO()
// .setType(2)
// .setData(new NotifyDTO().setSubject(subject).setContent(content));
// sseManagerService.send(user.getId(), message);
// } catch (IOException e) {
// log.error("发送SSE失败", e);
// }
}
@Override
public boolean check(UserDTO user) {
Object value = redisTemplate.opsForHash().get("message:config:" + user.getId(), Constant.REDIS_KEY_MESSAGECONFIG_APP);
return Objects.isNull(value) || (boolean) value;
}
}

View File

@ -88,8 +88,8 @@
</tr>
<tr>
<td colspan="4">
<div th:each="file:${ticket.files}">
<a th:href="${file.url}" th:text="${file.name}"></a>
<div>
<a th:each="file:${ticket.files}" th:href="${file.url}" th:text="${file.name}"></a>
</div>
</td>
</tr>
@ -98,7 +98,7 @@
</tr>
<tr>
<td colspan="4">
<div style="background-color: red;" th:each="file:${ticket.images}">
<div th:each="file:${ticket.images}">
<img class="cimg" alt="" th:src="${file.url}"/>
</div>
</td>

View File

@ -1,29 +0,0 @@
package com.nflg.mobilebroken.cfs.controller;
import com.nflg.mobilebroken.starter.service.impl.AdminSSEManagerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Collection;
/**
* 统计分析相关
*/
@RestController
@RequestMapping("/analysis")
public class AnalysisController extends ControllerBase{
@Resource
private AdminSSEManagerService adminSSEManagerService;
/**
* 获取当前已连接SSE的管理端用户列表
* @return 当前已连接SSE的管理端用户列表
*/
@GetMapping("getSSEConnects")
public Collection<Integer> getSSEConnects(){
return adminSSEManagerService.getUserIds();
}
}

View File

@ -1,36 +0,0 @@
package com.nflg.mobilebroken.cfs.controller;
import com.nflg.mobilebroken.starter.service.impl.AdminSSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
/**
* sse相关接口
* 曹鹏飞
*/
@RestController
@Slf4j
@RequestMapping("/sse")
//@SaUserCheckLogin
public class SSEController extends ControllerBase {
@Resource
private AdminSSEManagerService adminSSEManagerService;
/**
* 建立sse连接
*
* @param userId 用户id
*/
@GetMapping(value = "connect",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter connect(@RequestParam Integer userId) {
return adminSSEManagerService.connect(userId);
}
}

View File

@ -1,17 +1,23 @@
package com.nflg.mobilebroken.cfs.controller;
import com.nflg.mobilebroken.cfs.publisher.TicketEventPublisher;
import cn.hutool.core.date.DatePattern;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.util.MultilingualUtil;
import com.nflg.mobilebroken.repository.entity.AppUser;
import com.nflg.mobilebroken.repository.entity.Ticket;
import com.nflg.mobilebroken.repository.service.IAppUserService;
import com.nflg.mobilebroken.repository.service.IDictionaryItemTranslateService;
import com.nflg.mobilebroken.repository.service.ITicketService;
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
import com.nflg.mobilebroken.starter.service.EmailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@RestController
@Slf4j
@ -19,27 +25,38 @@ import javax.annotation.Resource;
public class TestController extends ControllerBase {
@Resource
private APPSSEManagerService sseManagerService;
@Resource
private TicketEventPublisher ticketEventPublisher;
private IDictionaryItemTranslateService dictionaryItemTranslateService;
@Resource
private ITicketService ticketService;
// @GetMapping("sse/send")
// public ApiResult<Void> sendSse(@RequestParam String userId, @RequestParam String message) throws IOException {
// SSEMessageDTO messageDTO = new SSEMessageDTO()
// .setType(2)
// .setData(new NotifyDTO().setSubject("消息测试").setContent("消息内容"));
// sseManagerService.send(Integer.valueOf(userId), messageDTO);
// return ApiResult.success();
// }
@Resource
private IAppUserService appUserService;
@GetMapping("sss")
public ApiResult sss(){
Ticket ticket =ticketService.getById(8);
ticketEventPublisher.publishTicketCreateEvent(ticket, MultilingualUtil.getLanguage(), MultilingualUtil.getZone());
@Resource
private EmailService emailService;
@GetMapping("sendEmail")
public ApiResult sendEmail() throws MessagingException {
Ticket ticket =ticketService.getById(1);
AppUser appUser=appUserService.getById(ticket.getUserId());
String subject=dictionaryItemTranslateService.getValueByCode(Constant.DICTIONARY_EMAIL_NOTIFY,Constant.DICTIONARY_ITEM_EMAIL_TITLE_TICKET_CREATE,Constant.DEFAULT_LANGUAGE_CODE);
String content=dictionaryItemTranslateService.getValueByCode(Constant.DICTIONARY_EMAIL_NOTIFY,Constant.DICTIONARY_ITEM_EMAIL_CONTENT_TICKET_NOTIFY,Constant.DEFAULT_LANGUAGE_CODE)
.replace("${no}",ticket.getNo())
.replace("${title}",ticket.getTitle())
.replace("${createUser}",appUser.getName())
.replace("${handleUser}","")
.replace("${createTime}",toTimeString(ticket.getCreateTime()))
.replace("${msg}",subject);
emailService.sendEmail("rakor@qq.com",subject,content);
return ApiResult.success();
}
private String toTimeString(LocalDateTime time){
// return time.atZone(ZoneOffset.UTC)
// .withZoneSameInstant(ZoneId.of(zone))
// .toLocalDateTime()
// .format(FORMATTER);
return time.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
}
}

View File

@ -186,10 +186,11 @@ public class TiketController extends ControllerBase {
@GetMapping("getTicket")
public ApiResult<TicketInfoVO> getTicket(@Valid @RequestParam @NotNull Integer id) {
Ticket ticket = ticketService.getById(id);
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
AppUser user = appUserService.getById(ticket.getUserId());
String areaName;
if (user.getIsPrimary()){
areaName=adminAreaService.getById(user.getAreaId()).getAreaName();
areaName=StrUtil.join(",",customerService.getAreas(Arrays.stream(user.getCompanyId().split(",")).map(Integer::parseInt).collect(Collectors.toList())));
}else {
areaName = appAreaService.getById(user.getAreaId()).getName();
}
@ -355,6 +356,18 @@ public class TiketController extends ControllerBase {
public ApiResult<Void> reopenTicket(@Valid @RequestParam @NotNull Integer id) {
Ticket ticket=ticketService.reopen(id);
ticketEventPublisher.publishTicketReopenEvent(ticket, MultilingualUtil.getLanguage(), MultilingualUtil.getZone());
ChatMessageDTO message = new ChatMessageDTO()
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
.setFrom("system")
.setTicketState(ticket.getState())
.setSenderId(0)
.setSenderName("服务助手")
.setContent("<b>重启议题</b><br/>用户重启议题,请继续关注此工单信息。")
.setCreateTime(Instant.now());
ticketChatService.addMessage(id, message);
//推送消息
ssePushService.sendTicketMessageToAdmin(id,message);
ssePushService.sendTicketMessageToApp(id,message);
return ApiResult.success();
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nflg.mobilebroken.cfs.service.WXQRCodeService;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.constant.MessageSubType;
@ -265,7 +266,16 @@ public class UserController extends ControllerBase {
@PostMapping("deleteUser")
//@SaUserCheckRole("primary")
public ApiResult<Boolean> deleteUser(@Valid @RequestBody @NotEmpty List<Integer> ids){
return ApiResult.success(appUserService.removeByIds(ids));
appUserService.remove(new LambdaQueryWrapper<AppUser>()
.eq(AppUser::getIsPrimary, false)
.eq(AppUser::getCreateBy, AppUserUtil.getUserName())
.in(AppUser::getId, ids));
appUserApplyforService.remove(new LambdaQueryWrapper<AppUserApplyfor>()
.eq(AppUserApplyfor::getState, 0)
.eq(AppUserApplyfor::getIsPrimary, false)
.eq(AppUserApplyfor::getCreateBy, AppUserUtil.getUserId())
.in(AppUserApplyfor::getId, ids));
return ApiResult.success(true);
}
/**

View File

@ -18,8 +18,6 @@ import org.springframework.context.ApplicationEvent;
import javax.mail.MessagingException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;
@ -124,9 +122,10 @@ public class TicketCreateEvent extends ApplicationEvent implements ApplicationCo
}
private String toTimeString(LocalDateTime time){
return time.atZone(ZoneOffset.UTC)
.withZoneSameInstant(ZoneId.of(zone))
.toLocalDateTime()
.format(FORMATTER);
// return time.atZone(ZoneOffset.UTC)
// .withZoneSameInstant(ZoneId.of(zone))
// .toLocalDateTime()
// .format(FORMATTER);
return time.format(FORMATTER);
}
}

View File

@ -37,6 +37,17 @@ public class SsePushService {
}
}
public void sendTicketMessageToApp(Integer ticketId, ChatMessageDTO message){
try {
PushRequest request=new PushRequest().setTicketId(ticketId).setMessage(buildMessage(message));
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<ApiResult> response = restTemplate.postForEntity(sseUrl+"/sse/app/push",request, ApiResult.class);
log.debug("发送消息结果:{}", JSONUtil.toJsonStr(response.getBody()));
} catch (Exception e) {
log.error("发送消息出错", e);
}
}
private ChatMessageVO buildMessage(ChatMessageDTO message){
String zone = MultilingualUtil.getZone();
ZoneId zoneId = ZoneId.of(zone);

View File

@ -32,4 +32,7 @@ public class AdminTicketSearchRequest extends TicketSearchRequest {
//收藏夹id
private Integer favouritesId;
//区域编码
private String areaCode;
}

View File

@ -3,8 +3,6 @@ package com.nflg.mobilebroken.common.pojo.request;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
@EqualsAndHashCode(callSuper = false)
@Data
public class AppUserUpdateRequest extends PrimaryAppUserAddRequest {
@ -15,6 +13,5 @@ public class AppUserUpdateRequest extends PrimaryAppUserAddRequest {
private Boolean enable;
//区域id
@NotNull
private Integer areaId;
}

View File

@ -55,7 +55,11 @@ public class AdminTicketVO {
@ExcelColumn("解决方案")
private String solution;
//区域名称
//代理区域
@ExcelColumn("代理区域")
private String agentAreaName;
//区域
@ExcelColumn("区域")
private String areaName;

View File

@ -46,6 +46,9 @@ public class AppUserForAdminVO {
private String areaName;
public String getAreaName(){
if (StrUtil.isBlank(areaName)){
return areaName;
}
return StrUtil.join(",",Arrays.stream(areaName.split(",")).distinct().collect(Collectors.toList()));
}

View File

@ -27,6 +27,10 @@ public class FileVO {
public String getSourceDesc() {
if (source == 0) {
return "工单";
}else if (source==1){
return "代理商";
}else if (source==2){
return "账号";
}
return "未知";
}

View File

@ -94,6 +94,11 @@ public class AppUserApplyfor implements Serializable {
*/
private String salesUserName;
/**
* 是否主账号
*/
private Boolean isPrimary;
/**
* 创建人id
*/

View File

@ -4,9 +4,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.dto.ExportPartDTO;
import com.nflg.mobilebroken.common.pojo.query.PageBaseQuery;
import com.nflg.mobilebroken.common.pojo.vo.DepartmentSimpleVO;
import com.nflg.mobilebroken.repository.entity.DeviceComponent;
import com.nflg.mobilebroken.repository.entity.TBaseDepartment;
import com.nflg.mobilebroken.repository.entity.TBasePart;
import org.apache.ibatis.annotations.Param;
@ -25,4 +22,6 @@ public interface ITBasePartService extends IService<TBasePart> {
Page<TBasePart> selectListByPage(@Param("query") PageBaseQuery query);
List<ExportPartDTO> exportPart(@Param("partNo")String partNo, @Param("partName") String partName);
List<String> getSimpleList(String name);
}

View File

@ -172,9 +172,9 @@ public class AppUserApplyforServiceImpl extends ServiceImpl<AppUserApplyforMappe
}
vo.setApplyfor(applyforInfo);
appUser = appUserService.getById(applyfor.getCreateBy());
TBaseArea area = baseAreaService.getById(appUser.getAreaId());
List<String> areas=customerService.getAreas(Arrays.stream(appUser.getCompanyId().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
vo.setUser(new AppUserVO()
.setAreaName(area.getAreaName())
.setAreaName(StrUtil.join(",",areas))
.setSalesUserName(appUser.getSalesUserName())
.setState(1)
.setTitle(Objects.isNull(appUser.getTitleId()) ? "" : positionService.getById(appUser.getTitleId()).getPositionName())

View File

@ -105,9 +105,6 @@ public class DictionaryItemServiceImpl extends ServiceImpl<DictionaryItemMapper,
List<DictionaryItemTranslate> forAdd = new ArrayList<>();
List<DictionaryItemTranslate> forUpdate = new ArrayList<>();
for (TranslateMap translate : request.getLanguages()) {
if(StrUtil.isBlank(translate.getValue())){
continue;
}
DictionaryItemTranslate t = new DictionaryItemTranslate()
.setDictionaryItemId(id)
.setLanguageCode(translate.getCode())

View File

@ -1,5 +1,6 @@
package com.nflg.mobilebroken.repository.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.pojo.dto.ExportPartDTO;
@ -11,6 +12,7 @@ import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
@ -31,4 +33,15 @@ public class TBasePartServiceImpl extends ServiceImpl<TBasePartMapper, TBasePart
public List<ExportPartDTO> exportPart(@Param("partNo")String partNo, @Param("partName") String partName){
return this.getBaseMapper().exportPart(partNo,partName);
}
@Override
public List<String> getSimpleList(String name) {
return lambdaQuery()
.eq(TBasePart::getEnable, 1)
.like(StrUtil.isNotBlank(name),TBasePart::getPartName, name)
.list()
.stream()
.map(TBasePart::getPartName)
.collect(Collectors.toList());
}
}

View File

@ -119,7 +119,8 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
public Ticket assignmentTicket(AssignmentTicketRequest request) {
Ticket ticket = getById(request.getTicketId());
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.PendingProcessing.getState())).throwMessage("工单状态异常");
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.PendingProcessing.getState()))
.throwMessage("非待处理状态不能分派工单");
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
.throwMessage("你无权分派工单");
@ -172,11 +173,11 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
public Ticket completeTicket(Integer id) {
Ticket ticket=getById(id);
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()))
.throwMessage("工单状态不允许完成");
.throwMessage("非处理中状态不允许完成");
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
tickerMangagers.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
.throwMessage("你无权添加处理人");
.throwMessage("你无权完成工单");
ticket.setState(TicketState.ProcessingCompleted.getState());
ticket.setCurrentHandle(AdminUserUtil.getUserId());
ticket.setUpdateTime(LocalDateTime.now());
@ -189,7 +190,7 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
Ticket ticket = getById(request.getTicketId());
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.ProcessingCompleted.getState()))
.throwMessage("工单状态不允许关闭");
.throwMessage("非处理完成状态不允许关闭");
VUtils.trueThrowBusinessError(!ticketEvaluateService.lambdaQuery()
.eq(TicketEvaluate::getTicketId, request.getTicketId())
.exists())

View File

@ -24,7 +24,7 @@
SELECT au.id
FROM t_base_position p
INNER JOIN admin_user au ON au.title_id=p.id
WHERE p.position_code IN
WHERE au.state=1 AND au.is_del=0 AND p.position_code IN
<foreach collection="titleCodes" item="titleCode" separator="," open="(" close=")">
#{titleCode}
</foreach>

View File

@ -102,7 +102,7 @@
LEFT JOIN app_area aa ON au.area_id=aa.id
LEFT JOIN app_user_applyfor aua ON aua.user_id=au.id AND aua.state=0
LEFT JOIN t_base_position p ON au.title_id=p.id
<where>
WHERE au.is_del=0
<if test="loginName!=null and loginName!=''">
AND au.login_name LIKE concat('%', #{loginName}, '%')
</if>
@ -124,10 +124,10 @@
<if test="state==2">
AND aua.id IS NULL AND CONVERT_TZ(NOW(), @@session.time_zone, '+00:00') >= au.expire_time
</if>
</where>
UNION
SELECT CONCAT('f-',aua.id) AS 'key',aua.id,aua.user_avatar AS 'avatar',aua.user_email AS 'loginName',aua.`user_name` AS 'userName',fun_getUserCompanys(aua.company_id) AS 'companyName',aua.user_name AS 'name',aua.user_email AS 'email',aua.sales_user_name,IF(aua.is_primary,fun_getPrimaryUserArea(aua.company_id),aa.`name`) AS 'areaName',0 AS 'userState',null AS 'expireTime',0 AS 'state',aua.create_by,aua.create_time,null AS 'updateBy',null AS 'updateTime',null AS 'lastLoginTime',aua.is_primary,aua.company_id,aua.user_phone AS 'phone',aua.area_id,aua.language_code,p.position_name AS 'title',aua.title_id
SELECT CONCAT('f-',aua.id) AS 'key',aua.id,aua.user_avatar AS 'avatar',aua.user_email AS 'loginName',aua.`user_name` AS 'userName',fun_getUserCompanys(aua.company_id) AS 'companyName',aua.user_name AS 'name',aua.user_email AS 'email',aua.sales_user_name,IF(aua.is_primary,fun_getPrimaryUserArea(aua.company_id),aa.`name`) AS 'areaName',0 AS 'userState',null AS 'expireTime',0 AS 'state',au.name AS 'createBy',aua.create_time,null AS 'updateBy',null AS 'updateTime',null AS 'lastLoginTime',aua.is_primary,aua.company_id,aua.user_phone AS 'phone',aua.area_id,aua.language_code,p.position_name AS 'title',aua.title_id
FROM app_user_applyfor aua
LEFT JOIN app_user au ON au.id=aua.create_by
LEFT JOIN app_area aa ON aua.area_id=aa.id
LEFT JOIN t_base_position p ON aua.title_id=p.id
WHERE aua.type=0 AND aua.state=0

View File

@ -51,7 +51,8 @@
SELECT d.device_no AS 'deviceNo',d.device_name AS 'deviceName',d.model_no AS 'modelNo',d.device_type AS 'deviceType',d.shipment_date AS 'shipmentDate'
FROM device d
INNER JOIN t_base_customer c ON d.agent_code=c.agency_company_code
WHERE d.data_valid_state=1 AND c.id IN
INNER JOIN dictionary_item di ON di.id=d.device_state
WHERE d.data_valid_state=1 AND di.`code`='Normal' AND c.id IN
<foreach collection="companyIds" open="(" close=")" item="companyId" separator=",">
#{companyId}
</foreach>
@ -94,6 +95,6 @@
FROM device_component_detail dcd
INNER JOIN t_base_part p ON dcd.model_part_id = p.id
LEFT JOIN t_base_language_data ld ON dcd.model_part_id = ld.source_id
WHERE dcd.device_component_id=#{componentId} AND ld.language_code=#{language}
WHERE p.enable=1 AND dcd.device_component_id=#{componentId} AND ld.language_code=#{language}
</select>
</mapper>

View File

@ -50,8 +50,8 @@
<if test="request.companyId!=null">
AND u.company_id=#{request.companyId}
</if>
<if test="request.areaId!=null">
AND u.area_id=#{request.areaId}
<if test="request.areaCode!=null and request.areaCode!=''">
AND FIND_IN_SET(#{request.areaCode},c.area_code)>0
</if>
<if test="request.question!=null and request.question!=''">
AND t.question=#{request.question}
@ -78,11 +78,10 @@
</sql>
<select id="searchMy" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
SELECT t.*,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
SELECT t.*,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
,u.`name` AS 'createBy',t.handle
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
LEFT JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=0
WHERE t.user_id=#{userId} AND t.state!=4
@ -91,10 +90,9 @@
</select>
<select id="searchFollow" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
SELECT t.*,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName',true AS 'followed',u.`name` AS 'createBy',true AS 'followed',t.handle
SELECT t.*,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),a2.`name`) AS 'areaName',true AS 'followed',u.`name` AS 'createBy',true AS 'followed',t.handle
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.from=0
WHERE tf.user_id=#{userId} AND t.state!=4
@ -103,11 +101,10 @@
</select>
<select id="searchArea" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
SELECT t.*,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
SELECT t.*,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
,u.`name` AS 'createBy',t.handle
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
LEFT JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=0
WHERE t.state!=4 AND u.company_id IN
@ -119,7 +116,8 @@
</select>
<select id="searchFromAdmin" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',IF(tf.id IS NULL, false, true) AS 'followed',auc.user_name AS 'cqm'
@ -128,7 +126,6 @@
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_customer c ON u.company_id=c.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
LEFT JOIN t_base_device_type dt ON d.device_type=dt.device_type
@ -150,7 +147,8 @@
<!-- </select>-->
<select id="searchAllFromAdmin" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',IF(tf.id IS NULL, false, true) AS 'followed',auc.user_name AS 'cqm'
@ -159,7 +157,6 @@
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_customer c ON u.company_id=c.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
LEFT JOIN t_base_device_type dt ON d.device_type=dt.device_type
@ -172,7 +169,8 @@
</select>
<select id="searchFromAdminAndFollow" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',true AS 'followed',auc.user_name AS 'cqm'
@ -181,7 +179,6 @@
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_customer c ON u.company_id=c.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=1
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
@ -194,7 +191,8 @@
</select>
<select id="searchAllFromAdminAndFollow" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',true AS 'followed'
,auc.user_name AS 'cqm',t.solve_time AS 'closeTime',u.name AS 'primaryUserName',auh.user_name AS 'currentHandle'
@ -202,7 +200,6 @@
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_customer c ON u.company_id=c.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=1
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
@ -218,11 +215,15 @@
SELECT t.id, t.no, t.title
FROM ticket_follow tf
INNER JOIN ticket t ON tf.ticket_id = t.id
WHERE tf.`from`=1 AND tf.user_id=#{userId} AND tf.favorites_id=#{favoritesId}
WHERE tf.`from` = 1
AND tf.user_id = #{userId}
AND tf.favorites_id = #{favoritesId}
ORDER BY t.id DESC
</select>
<select id="searchByFavouritesId" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',true AS 'followed',auc.user_name AS 'cqm'
@ -231,7 +232,6 @@
FROM ticket t
LEFT JOIN app_user u ON t.user_id=u.id
LEFT JOIN t_base_customer c ON u.company_id=c.id
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
LEFT JOIN app_area a2 ON u.area_id=a2.id
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=1 AND tf.favorites_id=#{favouritesId}
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1

View File

@ -1,79 +0,0 @@
package com.nflg.mobilebroken.starter.service;
import com.nflg.mobilebroken.common.constant.STATE;
import com.nflg.mobilebroken.common.util.VUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
@Slf4j
public class SSEManagerBase {
private static boolean IS_SHUTDOWN = false;
protected void check(){
VUtils.trueThrow(IS_SHUTDOWN).throwMessage(STATE.ServiceConnectRefused,"SSE服务已关闭");
}
protected static void shutdown(Map<Integer, SseEmitter> emitters) {
IS_SHUTDOWN=true;
log.warn("准备关闭SSE服务");
emitters.forEach((k,v)->{
try {
v.send("因SSE服务关闭,连接即将断开");
}catch (Exception ex){
log.error("SSE发送消息失败:"+k,ex);
}
v.complete();
});
log.warn("SSE服务已关闭");
}
protected static void close(SseEmitter emitter){
emitter.complete();
}
protected SseEmitter connect(Integer userId, Map<Integer, SseEmitter> emitters) {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
SseEmitter old=emitters.put(userId, emitter);
if (Objects.nonNull(old)){
log.warn("停止旧连接:"+userId);
try {
old.send(SseEmitter.event().name("被踢下线").data("你已在其他地方连接"));
old.complete();
} catch (Exception e) {
old.completeWithError(e);
}
}
emitter.onError((ex) -> {
emitters.remove(userId);
emitter.complete();
log.error("SSE异常:"+userId, ex);
});
emitter.onTimeout(() -> {
emitters.remove(userId);
emitter.complete();
log.error("SSE超时:"+userId);
});
emitter.onCompletion(() -> {
emitters.remove(userId);
emitter.complete();
log.error("SSE完成:"+userId);
});
try {
emitter.send(SseEmitter.event().data("已连接").reconnectTime(5000));
} catch (IOException e) {
log.error("sse发送数据出错", e);
}
return emitter;
}
protected void send(Object message, SseEmitter emitter) throws IOException {
VUtils.trueThrowBusinessError(Objects.isNull(emitter)).throwMessage("没有找到sse");
log.error("没有找到sse: ");
emitter.send(message);
}
}

View File

@ -1,20 +0,0 @@
package com.nflg.mobilebroken.starter.service;
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Collection;
public interface SSEManagerService {
SseEmitter connect(Integer userId);
void send(Integer userId, SSEMessageDTO message) throws IOException;
void close(Integer userId);
void shutdown();
Collection<Integer> getUserIds();
}

View File

@ -1,70 +0,0 @@
package com.nflg.mobilebroken.starter.service.impl;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
import com.nflg.mobilebroken.starter.service.SSEManagerBase;
import com.nflg.mobilebroken.starter.service.SSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Service
@Slf4j
public class APPSSEManagerService extends SSEManagerBase implements SSEManagerService {
public static final Map<Integer, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
@Override
public SseEmitter connect(Integer userId) {
check();
log.info("APP端SSE已连接:"+userId);
return connect(userId,EMITTERS);
}
@Override
public void send(Integer userId, SSEMessageDTO message) throws IOException {
log.info(StrUtil.format("APP端SSE发送消息,用户id: {},内容: {}", userId, message));
SseEmitter emitter = EMITTERS.get(userId);
if (Objects.isNull(emitter)) {
log.error("用户未连接SSE: " + userId);
} else {
send(message, emitter);
}
}
@Override
public void close(Integer userId) {
log.info("APP端SSE连接主动关闭:"+userId);
close(EMITTERS.remove(userId));
}
@Override
public void shutdown() {
shutdown(EMITTERS);
}
@Override
public Collection<Integer> getUserIds() {
return EMITTERS.keySet();
}
@PreDestroy
public void cleanup() {
log.info("释放SSE连接");
for (SseEmitter emitter : EMITTERS.values()) {
try {
emitter.complete();
} catch (Exception e) {
emitter.completeWithError(e);
}
}
EMITTERS.clear();
}
}

View File

@ -1,70 +0,0 @@
package com.nflg.mobilebroken.starter.service.impl;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
import com.nflg.mobilebroken.starter.service.SSEManagerBase;
import com.nflg.mobilebroken.starter.service.SSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Service
@Slf4j
public class AdminSSEManagerService extends SSEManagerBase implements SSEManagerService {
protected static final Map<Integer, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
@Override
public SseEmitter connect(Integer userId) {
check();
log.info("管理端SSE已连接:"+userId);
return connect(userId,EMITTERS);
}
@Override
public void send(Integer userId, SSEMessageDTO message) throws IOException {
log.info(StrUtil.format("管理端SSE发送消息,用户id: {},内容: {}", userId, message));
SseEmitter emitter = EMITTERS.get(userId);
if (Objects.isNull(emitter)) {
log.error("用户未连接SSE: " + userId);
} else {
send(message, emitter);
}
}
@Override
public void close(Integer userId) {
close(EMITTERS.remove(userId));
log.info("管理端SSE连接主动关闭:"+userId);
}
@Override
public void shutdown() {
shutdown(EMITTERS);
}
@Override
public Collection<Integer> getUserIds() {
return EMITTERS.keySet();
}
@PreDestroy
public void cleanup() {
log.info("释放SSE连接");
for (SseEmitter emitter : EMITTERS.values()) {
try {
emitter.complete();
} catch (Exception e) {
emitter.completeWithError(e);
}
}
EMITTERS.clear();
}
}