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

This commit is contained in:
大米 2025-02-07 16:37:27 +08:00
commit c48a5c34be
29 changed files with 278 additions and 122 deletions

View File

@ -0,0 +1,75 @@
package com.nflg.mobilebroken.admin.controller;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.constant.STATE;
import com.nflg.mobilebroken.common.exception.NflgException;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.starter.service.FileUploadService;
import org.springframework.web.bind.annotation.PostMapping;
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.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* 文件上传相关接口
*
* @author 曹鹏飞
**/
@RestController
@RequestMapping("/file")
public class FileController extends ControllerBase {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
@Resource
private FileUploadService fileUploadService;
/**
* 上传单个文件
*
* @param file 要上传的文件
* @return 可访问的文件url
*/
@PostMapping("uploadSingleFile")
public ApiResult<String> uploadSingleFile(@RequestParam("file") MultipartFile file) {
try {
return ApiResult.success(fileUploadService.upload(buildFilePath(file.getOriginalFilename()), file));
} catch (Exception ex) {
throw new NflgException(STATE.BusinessError, "上传文件失败:" + ex.getMessage());
}
}
private String buildFilePath(String fileName) {
return StrUtil.format("admin/{}/{}/{}/{}", LocalDateTime.now().format(FORMATTER), AdminUserUtil.getUserId(),
RandomUtil.randomString(4), fileName);
}
/**
* 上传多个文件
*
* @param files 要上传的文件列表
* @return 可访问的文件url列表
*/
@PostMapping("uploadMultipleFiles")
public ApiResult<List<String>> uploadMultipleFiles(@Valid @RequestParam("files") @NotEmpty List<MultipartFile> files) {
try {
List<String> list = new ArrayList<>();
for (MultipartFile f : files) {
list.add(fileUploadService.upload(buildFilePath(f.getOriginalFilename()), f));
}
return ApiResult.success(list);
} catch (Exception ex) {
throw new NflgException(STATE.BusinessError, "上传文件失败:" + ex.getMessage());
}
}
}

View File

@ -24,7 +24,7 @@ public class SSEController extends ControllerBase {
@GetMapping(value = "connect", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter connect(@RequestParam String userId) {
SseEmitter sse = adminSSEManagerService.connect(userId);
SseEmitter sse = adminSSEManagerService.connect(Integer.valueOf(userId));
try {
sse.send("您已连接");
} catch (IOException e) {

View File

@ -1,6 +1,8 @@
package com.nflg.mobilebroken.admin.service.impl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.dto.NotifyDTO;
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
import com.nflg.mobilebroken.common.pojo.dto.UserDTO;
import com.nflg.mobilebroken.starter.service.INotifyPushService;
import com.nflg.mobilebroken.starter.service.SSEManagerService;
@ -27,7 +29,10 @@ public class SSEINotifyPushService implements INotifyPushService {
@Override
public void push(UserDTO user, String subject, String content) {
try {
sseManagerService.send(user.getId().toString(), subject, content);
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);
}

View File

@ -50,7 +50,7 @@ public class FileController extends ControllerBase {
}
private String buildFilePath(String fileName){
return StrUtil.format("{}/{}/{}/{}", LocalDateTime.now().format(FORMATTER), AppUserUtil.getUserId(),
return StrUtil.format("cfs/{}/{}/{}/{}", LocalDateTime.now().format(FORMATTER), AppUserUtil.getUserId(),
RandomUtil.randomString(4),fileName);
}
@ -67,8 +67,8 @@ public class FileController extends ControllerBase {
list.add(fileUploadService.upload(buildFilePath(f.getOriginalFilename()), f));
}
return ApiResult.success(list);
}catch (Exception ex){
throw new NflgException(STATE.BusinessError,"上传文件失败:"+ex.getMessage());
} catch (Exception ex) {
throw new NflgException(STATE.BusinessError, "上传文件失败:" + ex.getMessage());
}
}
}
}

View File

@ -1,7 +1,5 @@
package com.nflg.mobilebroken.cfs.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
@ -43,11 +41,7 @@ public class MessageController extends ControllerBase {
*/
@PostMapping("searchMessages")
public ApiResult<PageData<AppMessageVO>> searchMessages(@RequestBody AppMessageSearchRequest request) {
IPage<AppMessageVO> page = new Page<>();
page.setCurrent(request.getPage());
page.setSize(request.getPageSize());
appMessageService.search(AppUserUtil.getUserId(), request.getTitle(), page);
return ApiResult.success(page);
return ApiResult.success(appMessageService.search(AppUserUtil.getUserId(), request));
}
/**
@ -79,11 +73,7 @@ public class MessageController extends ControllerBase {
*/
@GetMapping("getNotReadMessages")
public ApiResult<PageData<AppMessageVO>> getNotReadMessages(@RequestParam(defaultValue = "10") Integer num) {
IPage<AppMessageVO> page = new Page<>();
page.setCurrent(1);
page.setSize(num);
appMessageService.getNotReadMessage(AppUserUtil.getUserId(), num, page);
return ApiResult.success(page);
return ApiResult.success(appMessageService.getNotReadMessage(AppUserUtil.getUserId(), num));
}
/**

View File

@ -28,7 +28,7 @@ public class SSEController extends ControllerBase {
private APPSSEManagerService sseManagerService;
@GetMapping(value = "connect",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter connect(@RequestParam String userId){
public SseEmitter connect(@RequestParam Integer userId) {
SseEmitter sse=sseManagerService.connect(userId);
try {
sse.send("您已连接");

View File

@ -1,6 +1,8 @@
package com.nflg.mobilebroken.cfs.controller;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.dto.NotifyDTO;
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
@ -21,7 +23,10 @@ public class TestController extends ControllerBase {
@GetMapping("sse/send")
public ApiResult<Void> sendSse(@RequestParam String userId, @RequestParam String message) throws IOException {
sseManagerService.send(userId,"测试消息",message);
SSEMessageDTO messageDTO = new SSEMessageDTO()
.setType(2)
.setData(new NotifyDTO().setSubject("消息测试").setContent("消息内容"));
sseManagerService.send(Integer.valueOf(userId), messageDTO);
return ApiResult.success();
}
}

View File

@ -5,29 +5,38 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
import com.nflg.mobilebroken.common.pojo.dto.TicketChatDTO;
import com.nflg.mobilebroken.common.pojo.request.*;
import com.nflg.mobilebroken.common.pojo.vo.*;
import com.nflg.mobilebroken.common.util.AppUserUtil;
import com.nflg.mobilebroken.common.util.MultilingualUtil;
import com.nflg.mobilebroken.common.util.PageUtil;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.*;
import com.nflg.mobilebroken.repository.service.*;
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 工单相关接口
* @author 曹鹏飞
**/
@Slf4j
@RestController
@RequestMapping("/ticket")
//@SaUserCheckLogin
@ -42,8 +51,6 @@ public class TiketController extends ControllerBase {
@Resource
private ITicketFollowService ticketFollowService;
// @Resource
// private ITicketChatService ticketChatService;
@Resource
private TicketChatService ticketChatService;
@ -68,6 +75,9 @@ public class TiketController extends ControllerBase {
@Resource
private ITBaseCustomerService customerService;
@Resource
private APPSSEManagerService sseManagerService;
/**
* 搜索设备
*
@ -108,9 +118,9 @@ public class TiketController extends ControllerBase {
@PostMapping("/addTiket")
public ApiResult<Void> addTiket(@Valid @RequestBody TicketAddRequest request) {
Integer ticketId = ticketService.add(request, AppUserUtil.getUserId());
ticketChatService.add(new TicketChat()
ticketChatService.add(new TicketChatDTO()
.setTicketId(ticketId)
.setMessages(Collections.singletonList(new ChatMessageVO()
.setMessages(Collections.singletonList(new ChatMessageDTO()
.setFrom("system")
.setSenderId(0)
.setSenderName("服务助手")
@ -159,15 +169,21 @@ public class TiketController extends ControllerBase {
AppUser user = appUserService.getById(ticket.getUserId());
AppArea appArea = appAreaService.getById(user.getAreaId());
TBaseCustomer company = customerService.getById(Integer.valueOf(user.getCompanyId()));
DeviceInfoVO device = deviceService.getByDeviceNo(ticket.getDeviceNo());
TicketInfoVO vo = new TicketInfoVO()
.setId(ticket.getId())
.setTitle(ticket.getTitle())
.setDeviceNo(ticket.getDeviceNo())
.setModelNo(device.getModelNo())
.setComponent(ticket.getComponent())
.setUseTime(ticket.getUseTime())
.setDescription(ticket.getDescription())
.setState(ticket.getState())
.setAttachments(StrUtil.isNotBlank(ticket.getAttachments()) ? StrUtil.split(",", ticket.getAttachments()) : Collections.emptyList())
.setCreateUserId(ticket.getUserId())
.setCreateUserName(user.getName())
.setCreateUserAvatar(user.getAvatar())
.setCreateTime(ticket.getCreateTime())
.setAreaName(appArea.getName())
.setCompanyName(company.getAgencyCompanyName());
return ApiResult.success(vo);
@ -179,7 +195,7 @@ public class TiketController extends ControllerBase {
* @return 聊天记录
**/
@GetMapping("getChatMessages")
public ApiResult<List<ChatMessageVO>> getChatMessages(@Valid @RequestParam @NotNull Integer ticketId) {
public ApiResult<List<ChatMessageDTO>> getChatMessages(@Valid @RequestParam @NotNull Integer ticketId) {
return ApiResult.success(ticketChatService.getMessages(ticketId));
}
@ -189,10 +205,17 @@ public class TiketController extends ControllerBase {
**/
@PostMapping("addChatMessage")
public ApiResult<Void> addChatMessage(@Valid @RequestBody AddChatMessageRequest request){
ChatMessageVO message = new ChatMessageVO()
Ticket ticket = ticketService.getById(request.getTicketId());
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在");
VUtils.trueThrowBusinessError(Objects.equals(ticket.getState(), TicketState.Revoked.getState())
|| Objects.equals(ticket.getState(), TicketState.Closed.getState()))
.throwMessage("当前工单状态不允许发送消息");
AppUser user = appUserService.getById(AppUserUtil.getUserId());
ChatMessageDTO message = new ChatMessageDTO()
.setFrom("app")
.setSenderId(AppUserUtil.getUserId())
.setSenderName(AppUserUtil.getUserName())
.setSenderId(user.getId())
.setSenderName(user.getName())
.setSenderAvatar(user.getAvatar())
.setContent(request.getContent())
.setCreateTime(Instant.now())
.setAttachments(request.getAttachments());
@ -201,6 +224,20 @@ public class TiketController extends ControllerBase {
// chat.getMessages().add(message);
// ticketChatService.save(chat);
ticketChatService.addMessage(request.getTicketId(), message);
//推送消息
String handle = ticket.getHandle();
if (StrUtil.isNotBlank(handle)) {
SSEMessageDTO messageDTO = new SSEMessageDTO()
.setType(1)
.setData(message);
StrUtil.split(handle, ",").forEach(userId -> {
try {
sseManagerService.send(Integer.valueOf(userId), messageDTO);
} catch (IOException e) {
log.error("发送SSE消息出错", e);
}
});
}
return ApiResult.success();
}

View File

@ -51,6 +51,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -1,14 +1,18 @@
package com.nflg.mobilebroken.common.pojo.vo;
package com.nflg.mobilebroken.common.pojo.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import java.time.Instant;
import java.util.List;
@Data
@Accessors(chain = true)
public class ChatMessageVO {
public class ChatMessageDTO {
@Id
private String id;
//来源
private String from;
@ -19,6 +23,9 @@ public class ChatMessageVO {
// 发送者名称
private String senderName;
// 发送者头像
private String senderAvatar;
// 消息内容
private String content;
@ -29,5 +36,5 @@ public class ChatMessageVO {
private Instant createTime;
// 引用的消息
private ChatMessageVO quote;
private ChatMessageDTO quote;
}

View File

@ -0,0 +1,13 @@
package com.nflg.mobilebroken.common.pojo.dto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class NotifyDTO {
private String subject;
private String content;
}

View File

@ -0,0 +1,15 @@
package com.nflg.mobilebroken.common.pojo.dto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class SSEMessageDTO {
//类型1工单会话消息2消息提醒
private int type;
//消息内容
private Object data;
}

View File

@ -1,6 +1,5 @@
package com.nflg.mobilebroken.repository.entity;
package com.nflg.mobilebroken.common.pojo.dto;
import com.nflg.mobilebroken.common.pojo.vo.ChatMessageVO;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
@ -12,12 +11,12 @@ import java.util.List;
@Data
@Accessors(chain = true)
@Document(collection = "TicketChat")
public class TicketChat {
public class TicketChatDTO {
@Id
private String id;
private Integer ticketId;
private List<ChatMessageVO> messages = new ArrayList<>();
private List<ChatMessageDTO> messages = new ArrayList<>();
}

View File

@ -1,6 +1,6 @@
package com.nflg.mobilebroken.common.pojo.request;
import com.nflg.mobilebroken.common.pojo.vo.ChatMessageVO;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@ -22,5 +22,5 @@ public class AddChatMessageRequest {
private List<String> attachments;
// 引用的消息
private ChatMessageVO quote;
private ChatMessageDTO quote;
}

View File

@ -9,6 +9,8 @@ import java.time.LocalDateTime;
@Accessors(chain = true)
public class AppMessageVO {
private int id;
//工单id
private int ticketId;

View File

@ -3,6 +3,7 @@ package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
@Data
@ -27,6 +28,9 @@ public class TicketInfoVO {
//创建人头像
private String createUserAvatar;
//提交时间
private LocalDateTime createTime;
//工单状态
private Byte state;
@ -36,6 +40,18 @@ public class TicketInfoVO {
//所属区域
private String areaName;
//设备编号
private String deviceNo;
//设备机型
private String modelNo;
//问题部位
private String component;
//使用时长单位: 小时
private Integer useTime;
//附件
private List<String> attachments;
}

View File

@ -3,13 +3,14 @@ package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* <p>
* 用户端-用户
@ -85,9 +86,9 @@ public class AppUser implements Serializable {
private Boolean isPrimary;
/**
* 职位编码
* 职位id
*/
private String titleCode;
private Integer titleId;
/**
* 所属销售代表

View File

@ -75,9 +75,9 @@ public class AppUserApplyfor implements Serializable {
private Byte type;
/**
* 职位编码
* 职位id
*/
private String titleCode;
private Integer titleId;
/**
* 处理状态0待审核1审核通过2审核不通过

View File

@ -15,7 +15,7 @@ import com.nflg.mobilebroken.repository.entity.AppMessage;
*/
public interface AppMessageMapper extends BaseMapper<AppMessage> {
void getNotReadMessage(Integer userId, Integer num, IPage<AppMessageVO> page);
IPage<AppMessageVO> getNotReadMessage(Integer userId, Integer num, IPage<AppMessageVO> page);
void search(Integer userId, String title, IPage<AppMessageVO> page);
IPage<AppMessageVO> search(Integer userId, String title, IPage<AppMessageVO> page);
}

View File

@ -2,6 +2,7 @@ package com.nflg.mobilebroken.repository.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.request.AppMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AppMessageVO;
import com.nflg.mobilebroken.repository.entity.AppMessage;
@ -17,9 +18,9 @@ import java.util.List;
*/
public interface IAppMessageService extends IService<AppMessage> {
void getNotReadMessage(Integer userId, Integer num, IPage<AppMessageVO> page);
IPage<AppMessageVO> getNotReadMessage(Integer userId, Integer num);
void search(Integer userId, String title, IPage<AppMessageVO> page);
IPage<AppMessageVO> search(Integer userId, AppMessageSearchRequest request);
void setReaded(List<Integer> ids);

View File

@ -1,17 +0,0 @@
package com.nflg.mobilebroken.repository.service;
import com.nflg.mobilebroken.common.pojo.vo.ChatMessageVO;
import com.nflg.mobilebroken.repository.entity.TicketChat;
import org.apache.ibatis.annotations.Update;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
public interface ITicketChatService extends MongoRepository<TicketChat, String> {
@Query("{ 'ticketId': ?0 }")
TicketChat findByTicketId(Integer ticketId);
@Query("{ 'ticketId': ?0 }")
@Update("{ '$push': { 'messages': ?1 } }")
void pushMessage(Integer ticketId, ChatMessageVO message);
}

View File

@ -1,7 +1,7 @@
package com.nflg.mobilebroken.repository.service;
import com.nflg.mobilebroken.common.pojo.vo.ChatMessageVO;
import com.nflg.mobilebroken.repository.entity.TicketChat;
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
import com.nflg.mobilebroken.common.pojo.dto.TicketChatDTO;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@ -19,26 +19,26 @@ public class TicketChatService {
@Resource
private MongoTemplate mongoTemplate;
public void add(TicketChat ticketChat) {
mongoTemplate.save(ticketChat);
public void add(TicketChatDTO ticketChatDTO) {
mongoTemplate.save(ticketChatDTO);
}
public List<ChatMessageVO> getMessages(Integer ticketId) {
public List<ChatMessageDTO> getMessages(Integer ticketId) {
Query query = new Query(Criteria.where("ticketId").is(ticketId));
TicketChat ticketChat = mongoTemplate.findOne(query, TicketChat.class);
if (Objects.isNull(ticketChat)) {
TicketChatDTO ticketChatDTO = mongoTemplate.findOne(query, TicketChatDTO.class);
if (Objects.isNull(ticketChatDTO)) {
return Collections.emptyList();
} else {
return ticketChat.getMessages();
return ticketChatDTO.getMessages();
}
}
public void addMessage(Integer ticketId, ChatMessageVO newMessage) {
public void addMessage(Integer ticketId, ChatMessageDTO newMessage) {
// 创建查询条件查找 ticketId = ticketId TicketChat
Query query = new Query(Criteria.where("ticketId").is(ticketId));
// 创建更新操作 messages 列表中添加新消息
Update update = new Update().push("messages", newMessage);
// 执行更新操作
mongoTemplate.findAndModify(query, update, TicketChat.class);
mongoTemplate.findAndModify(query, update, TicketChatDTO.class);
}
}

View File

@ -1,7 +1,9 @@
package com.nflg.mobilebroken.repository.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.pojo.request.AppMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AppMessageVO;
import com.nflg.mobilebroken.repository.entity.AppMessage;
import com.nflg.mobilebroken.repository.mapper.AppMessageMapper;
@ -22,13 +24,13 @@ import java.util.List;
public class AppMessageServiceImpl extends ServiceImpl<AppMessageMapper, AppMessage> implements IAppMessageService {
@Override
public void getNotReadMessage(Integer userId, Integer num, IPage<AppMessageVO> page) {
baseMapper.getNotReadMessage(userId, num, page);
public IPage<AppMessageVO> getNotReadMessage(Integer userId, Integer num) {
return baseMapper.getNotReadMessage(userId, num, new Page<>(1, num));
}
@Override
public void search(Integer userId, String title, IPage<AppMessageVO> page) {
baseMapper.search(userId,title,page);
public IPage<AppMessageVO> search(Integer userId, AppMessageSearchRequest request) {
return baseMapper.search(userId, request.getTitle(), new Page<>(request.getPage(), request.getPageSize()));
}
@Override

View File

@ -63,6 +63,7 @@ public class AppUserApplyforServiceImpl extends ServiceImpl<AppUserApplyforMappe
.setState(AppUserApplyForState.PENDINGAPPROVAL.getState().byteValue())
.setAreaId(request.getAreaId())
.setCompanyId(request.getCompanyId())
.setTitleId(request.getTitleId())
.setType(AppUserApplyforType.ADD.getState().byteValue())
.setCreateBy(AdminUserUtil.getUserId())
.setCreateTime(LocalDateTime.now());
@ -99,10 +100,7 @@ public class AppUserApplyforServiceImpl extends ServiceImpl<AppUserApplyforMappe
VUtils.trueThrowBusinessError(Objects.isNull(applyfor)).throwMessage("审批信息不存在");
AppUserApplyforVO vo = new AppUserApplyforVO();
AppArea area = appAreaService.getById(applyfor.getAreaId());
TBasePosition position = positionService.lambdaQuery()
.eq(TBasePosition::getDataValidState, 1)
.eq(TBasePosition::getPositionCode, applyfor.getTitleCode())
.one();
TBasePosition position = positionService.getById(applyfor.getTitleId());
String titleName = Objects.isNull(position) ? "" : position.getPositionName();
vo.setApplyfor(new AppUserApplyforInfoVO()
.setAreaName(area.getName())
@ -141,7 +139,7 @@ public class AppUserApplyforServiceImpl extends ServiceImpl<AppUserApplyforMappe
.setPassword(PASSWORDENCODER.encode(request.getPassword()))
.setAreaId(applyfor.getAreaId())
.setCompanyId(String.valueOf(applyfor.getCompanyId()))
.setTitleCode(applyfor.getTitleCode())
.setTitleId(applyfor.getTitleId())
.setEnable(true)
.setCreateBy(applyfor.getCreateBy())
.setCreateTime(LocalDateTime.now())

View File

@ -2,7 +2,7 @@
<!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.AppMessageMapper">
<select id="getNotReadMessage">
<select id="getNotReadMessage" resultType="com.nflg.mobilebroken.common.pojo.vo.AppMessageVO">
SELECT t.id AS 'ticketId',t.`no` AS 'ticketNo',t.title AS 'ticketTitle',m.content,m.create_time AS 'createTime',u.`name` AS 'ticketCreateBy',t.create_time AS 'ticketCreateTime',t.handle AS 'ticketHandleBy',m.is_read AS 'isRead'
FROM app_message m
INNER JOIN ticket t ON m.ticket_id=t.id
@ -10,7 +10,7 @@
WHERE m.is_read=0 AND m.user_id=#{userId}
ORDER BY m.id
</select>
<select id="search">
<select id="search" resultType="com.nflg.mobilebroken.common.pojo.vo.AppMessageVO">
SELECT t.id AS 'ticketId',t.`no` AS 'ticketNo',t.title AS 'ticketTitle',m.content,m.create_time AS 'createTime',u.`name` AS 'ticketCreateBy',t.create_time AS 'ticketCreateTime',t.handle AS 'ticketHandleBy',m.is_read AS 'isRead'
FROM app_message m
INNER JOIN ticket t ON m.ticket_id=t.id

View File

@ -19,7 +19,25 @@ public class SSEManagerBase {
VUtils.trueThrow(IS_SHUTDOWN).throwMessage(STATE.ServiceConnectRefused,"SSE服务已关闭");
}
protected SseEmitter connect(String userId, Map<String, SseEmitter> emitters){
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);
emitters.put(userId, emitter);
emitter.onError((ex) -> {
@ -41,27 +59,9 @@ public class SSEManagerBase {
return emitter;
}
protected static void close(SseEmitter emitter){
emitter.complete();
}
protected static void shutdown(Map<String, 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服务已关闭");
}
public void send(String subject, String message,SseEmitter emitter) throws IOException {
protected void send(Object message, SseEmitter emitter) throws IOException {
VUtils.trueThrowBusinessError(Objects.isNull(emitter)).throwMessage("没有找到sse");
log.error("没有找到sse: ");
emitter.send(subject+":"+message);
emitter.send(message);
}
}

View File

@ -1,16 +1,17 @@
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;
public interface SSEManagerService {
SseEmitter connect(String userId);
SseEmitter connect(Integer userId);
void send(String userId,String subject, String message) throws IOException;
void send(Integer userId, SSEMessageDTO message) throws IOException;
void close(String userId);
void close(Integer userId);
void shutdown();
}

View File

@ -1,6 +1,7 @@
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;
@ -16,28 +17,28 @@ import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class APPSSEManagerService extends SSEManagerBase implements SSEManagerService {
public static final Map<String, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
public static final Map<Integer, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
@Override
public SseEmitter connect(String userId) {
public SseEmitter connect(Integer userId) {
check();
log.info("APP端SSE已连接:"+userId);
return connect(userId,EMITTERS);
}
@Override
public void send(String userId, String subject, String message) throws IOException {
log.info(StrUtil.format("APP端SSE发送消息,用户id: {},标题: {},内容: {}", userId, subject, message));
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(subject, message, emitter);
send(message, emitter);
}
}
@Override
public void close(String userId) {
public void close(Integer userId) {
log.info("APP端SSE连接主动关闭:"+userId);
close(EMITTERS.remove(userId));
}

View File

@ -1,6 +1,7 @@
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;
@ -16,28 +17,28 @@ import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class AdminSSEManagerService extends SSEManagerBase implements SSEManagerService {
protected static final Map<String, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
protected static final Map<Integer, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
@Override
public SseEmitter connect(String userId) {
public SseEmitter connect(Integer userId) {
check();
log.info("管理端SSE已连接:"+userId);
return connect(userId,EMITTERS);
}
@Override
public void send(String userId, String subject, String message) throws IOException {
log.info(StrUtil.format("管理端端SSE发送消息,用户id: {},标题: {},内容: {}", userId, subject, message));
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(subject, message, emitter);
send(message, emitter);
}
}
@Override
public void close(String userId) {
public void close(Integer userId) {
close(EMITTERS.remove(userId));
log.info("管理端SSE连接主动关闭:"+userId);
}