feat(message): 实现消息未读数量统计功能

- AdminMessage实体新增key字段用于唯一标识消息
- AdminMessageServiceImpl新增getNotReadMessageCount1方法,按key聚合未读消息
- AppMessageServiceImpl新增getNotReadMessageCount1方法,按ticketId聚合未读消息
- 新增AdminNotReadMessageCountVO和AdminNotReadTicketMessageCountVO数据结构
- 新增AppNotReadMessageCountVO和AppNotReadTicketMessageCountVO数据结构
- AdminMessageService和AppMessageService接口新增getNotReadMessageCount1方法声明
- Admin端和App端消息控制器新增获取未读消息数量接口getNotReadMessageCount1
- 修正工单解决方案相关消息的SubType枚举及接口调用
- 优化TicketSolutionServiceImpl中工单解决方案分组逻辑,改为按dictionaryItemId分组
This commit is contained in:
曹鹏飞 2025-12-19 14:01:11 +08:00
parent 27d33bc884
commit 8865f971f8
14 changed files with 168 additions and 29 deletions

View File

@ -9,6 +9,7 @@ import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.AdminMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.request.MessageConfigRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO;
import com.nflg.mobilebroken.common.pojo.vo.AdminNotReadMessageCountVO;
import com.nflg.mobilebroken.common.pojo.vo.MessageConfigVO;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.PageUtil;
@ -158,6 +159,16 @@ public class MessageController extends ControllerBase {
return ApiResult.success(adminMessageService.getNotReadMessageCount(AdminUserUtil.getUserId()));
}
/**
* 获取未读消息数量
* @return 未读消息数量
*/
@GetMapping("getNotReadMessageCount1")
@ApiMark(moduleName = "消息管理", apiName = "获取未读消息数量1")
public ApiResult<AdminNotReadMessageCountVO> getNotReadMessageCount1() {
return ApiResult.success(adminMessageService.getNotReadMessageCount1(AdminUserUtil.getUserId()));
}
/**
* 获取消息配置
* @return 消息配置

View File

@ -6,7 +6,9 @@ import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.AppMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.request.MessageConfigRequest;
import com.nflg.mobilebroken.common.pojo.vo.AppMessageVO;
import com.nflg.mobilebroken.common.pojo.vo.AppNotReadMessageCountVO;
import com.nflg.mobilebroken.common.pojo.vo.MessageConfigVO;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.AppUserUtil;
import com.nflg.mobilebroken.repository.service.IAppMessageService;
import org.springframework.data.redis.core.HashOperations;
@ -83,6 +85,15 @@ public class MessageController extends ControllerBase {
return ApiResult.success(appMessageService.getNotReadMessageCount(AppUserUtil.getUserId(),AppUserUtil.getFrom()));
}
/**
* 获取未读消息数量
* @return 未读消息数量
*/
@GetMapping("getNotReadMessageCount1")
public ApiResult<AppNotReadMessageCountVO> getNotReadMessageCount1() {
return ApiResult.success(appMessageService.getNotReadMessageCount1(AdminUserUtil.getUserId(), AppUserUtil.getFrom()));
}
/**
* 获取消息配置
* @return 消息配置

View File

@ -38,7 +38,10 @@ public enum MessageSubType {
//派工单完成
DispatchComplate(14, "派工单完成"),
//派工单延期审核结果
DispatchAuditResult(15, "派工单延期审核结果");
DispatchAuditResult(15, "派工单延期审核结果"),
//工单解决方案审核
TicketSolutionAuditResult(16, "工单解决方案审核结果"),
;
private final Integer state;
private final String description;

View File

@ -0,0 +1,18 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class AdminNotReadMessageCountVO {
/**
* 未读消息总数量
*/
private Integer count;
private List<AdminNotReadTicketMessageCountVO> items;
}

View File

@ -0,0 +1,18 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AdminNotReadTicketMessageCountVO {
/**
* 来源0工单1代理商账户审核2派工单3工服工单
*/
private Integer source;
private Long sourceId;
private Integer count;
}

View File

@ -0,0 +1,19 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class AppNotReadMessageCountVO {
/**
* 未读消息总数量
*/
private Integer count;
private List<AppNotReadTicketMessageCountVO> ticketItems;
}

View File

@ -0,0 +1,13 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AppNotReadTicketMessageCountVO {
private Long ticketId;
private Integer count;
}

View File

@ -860,22 +860,7 @@ public class TicketController extends ControllerBase {
@PostMapping("saveSolutionMeasures")
@ApiMark(moduleName = "工单管理", apiName = "保存工单解决方案措施")
public ApiResult<Void> saveSolutionMeasures(@Valid @RequestBody SolutionMeasuresSaveRequest request) {
GongfuTicket ticket = ticketSolutionService.saveSolutionMeasures1(request);
List<Integer> auditIds = deviceTypeService.getCqms(ticket.getDeviceNo());
auditIds.forEach(uid -> {
adminMessageService.add(
new AdminMessage()
.setNo(ticket.getNo())
.setTitle(ticket.getTitle())
.setUserId(uid)
.setSourceId(ticket.getId())
.setSource(3)
.setType(MessageType.WorkOrderAssignment.getState())
.setSubType(MessageSubType.TicketSolutionAudit.getState())
.setIsRead(false)
.setCreateTime(LocalDateTime.now())
);
});
ticketSolutionService.saveSolutionMeasures1(request);
return ApiResult.success();
}
@ -896,7 +881,7 @@ public class TicketController extends ControllerBase {
.setSourceId(ticket.getId())
.setSource(3)
.setType(MessageType.WorkOrderAssignment.getState())
.setSubType(MessageSubType.TicketSolutionAudit.getState())
.setSubType(MessageSubType.TicketSolutionAuditResult.getState())
.setIsRead(false)
.setCreateTime(LocalDateTime.now())
);

View File

@ -1,6 +1,7 @@
package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
@ -14,7 +15,6 @@ import java.time.LocalDateTime;
* <p>
*
* </p>
*
* @author 代码生成器生成
* @since 2025
*/
@ -73,4 +73,11 @@ public class AdminMessage implements Serializable {
* 创建时间
*/
private LocalDateTime createTime;
@TableField(exist = false)
private String key;
public String getKey() {
return userId + "|" + source + "|" + sourceId;
}
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.request.AdminMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO;
import com.nflg.mobilebroken.common.pojo.vo.AdminNotReadMessageCountVO;
import com.nflg.mobilebroken.repository.entity.AdminMessage;
import java.util.List;
@ -31,4 +32,6 @@ public interface IAdminMessageService extends IService<AdminMessage> {
Integer getNotReadMessageCount(Integer userId);
void remove(Integer source, Integer sourceId, Integer userId, Integer subType);
AdminNotReadMessageCountVO getNotReadMessageCount1(Integer userId);
}

View File

@ -4,6 +4,7 @@ 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.common.pojo.vo.AppNotReadMessageCountVO;
import com.nflg.mobilebroken.repository.entity.AppMessage;
import java.util.List;
@ -29,4 +30,6 @@ public interface IAppMessageService extends IService<AppMessage> {
void add(AppMessage message);
Integer getNotReadMessageCount(Integer userId,String from);
AppNotReadMessageCountVO getNotReadMessageCount1(Integer userId, String from);
}

View File

@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.request.AdminMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO;
import com.nflg.mobilebroken.common.pojo.vo.AdminNotReadMessageCountVO;
import com.nflg.mobilebroken.common.pojo.vo.AdminNotReadTicketMessageCountVO;
import com.nflg.mobilebroken.repository.entity.AdminMessage;
import com.nflg.mobilebroken.repository.mapper.AdminMessageMapper;
import com.nflg.mobilebroken.repository.service.IAdminMessageService;
@ -16,12 +18,12 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author 曹鹏飞
* @since 2025-01-23
*/
@ -98,4 +100,25 @@ public class AdminMessageServiceImpl extends ServiceImpl<AdminMessageMapper, Adm
.eq(AdminMessage::getUserId, userId)
.eq(AdminMessage::getSubType, subType));
}
@Override
public AdminNotReadMessageCountVO getNotReadMessageCount1(Integer userId) {
List<AdminMessage> datas = lambdaQuery()
.eq(AdminMessage::getIsRead, false)
.eq(AdminMessage::getUserId, userId)
.list();
return new AdminNotReadMessageCountVO()
.setCount(datas.size())
.setItems(datas.stream()
.collect(Collectors.groupingBy(AdminMessage::getKey))
.values()
.stream()
.map(items -> new AdminNotReadTicketMessageCountVO()
.setSource(items.get(0).getSource())
.setSourceId(items.get(0).getSourceId())
.setCount(items.size())
)
.collect(Collectors.toList())
);
}
}

View File

@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.request.AppMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AppMessageVO;
import com.nflg.mobilebroken.common.pojo.vo.AppNotReadMessageCountVO;
import com.nflg.mobilebroken.common.pojo.vo.AppNotReadTicketMessageCountVO;
import com.nflg.mobilebroken.repository.entity.AppMessage;
import com.nflg.mobilebroken.repository.mapper.AppMessageMapper;
import com.nflg.mobilebroken.repository.service.IAdminUserService;
@ -90,8 +92,10 @@ public class AppMessageServiceImpl extends ServiceImpl<AppMessageMapper, AppMess
remove(new LambdaQueryWrapper<AppMessage>()
.eq(AppMessage::getIsRead, false)
.eq(AppMessage::getSubType, message.getSubType())
.eq(AppMessage::getTicketId, message.getTicketId())
.eq(AppMessage::getUserId, message.getUserId())
.eq(AppMessage::getUserPlatform, message.getUserPlatform()));
.eq(AppMessage::getUserPlatform, message.getUserPlatform())
);
save(message);
setUnreadMessageCount(message.getUserId(), message.getUserPlatform());
}
@ -114,4 +118,25 @@ public class AppMessageServiceImpl extends ServiceImpl<AppMessageMapper, AppMess
return 0;
}
}
@Override
public AppNotReadMessageCountVO getNotReadMessageCount1(Integer userId, String from) {
List<AppMessage> datas = lambdaQuery()
.eq(AppMessage::getIsRead, false)
.eq(AppMessage::getUserId, userId)
.eq(AppMessage::getUserPlatform, from)
.list();
return new AppNotReadMessageCountVO()
.setCount(datas.size())
.setTicketItems(datas.stream()
.collect(Collectors.groupingBy(AppMessage::getTicketId))
.values()
.stream()
.map(items -> new AppNotReadTicketMessageCountVO()
.setTicketId(items.get(0).getTicketId())
.setCount(items.size())
)
.collect(Collectors.toList())
);
}
}

View File

@ -65,7 +65,7 @@ public class TicketSolutionServiceImpl extends ServiceImpl<TicketSolutionMapper,
initial = dictionaryItemService.getListByDictionaryCode(Constant.DICTIONARY_SOLUTION_MEASURES, Constant.DEFAULT_LANGUAGE_CODE);
}
List<TicketSolution> solutions = lambdaQuery().eq(TicketSolution::getTicketId, ticketId).orderByAsc(TicketSolution::getId).list();
Map<String, List<TicketSolution>> groupedSolutions = solutions.stream().collect(Collectors.groupingBy(TicketSolution::getDictionaryItemName, LinkedHashMap::new, Collectors.toList()));
Map<Integer, List<TicketSolution>> groupedSolutions = solutions.stream().collect(Collectors.groupingBy(TicketSolution::getDictionaryItemId, LinkedHashMap::new, Collectors.toList()));
SolutionMeasuresVO vo = new SolutionMeasuresVO();
if (SaTokenAdminUtil.isLogin()) {
if (ticket.getType() == 0) {
@ -92,7 +92,7 @@ public class TicketSolutionServiceImpl extends ServiceImpl<TicketSolutionMapper,
.collect(Collectors.toList());
} else if (CollectionUtil.isEmpty(initial)) {
items = groupedSolutions.entrySet().stream().map(ks -> new SolutionMeasuresItemVO()
.setName(ks.getKey())
.setName(ks.getValue().get(0).getDictionaryItemName())
.setItems(ks.getValue().stream().map(v -> new SolutionMeasuresDataItemVO()
.setId(Long.valueOf(v.getId()))
.setName(v.getDescription())
@ -104,7 +104,7 @@ public class TicketSolutionServiceImpl extends ServiceImpl<TicketSolutionMapper,
)).collect(Collectors.toList());
} else {
for (DictionaryItem it : initial) {
List<TicketSolution> values = groupedSolutions.get(it.getName());
List<TicketSolution> values = groupedSolutions.get(it.getId());
if (CollectionUtil.isEmpty(values)) {
items.add(new SolutionMeasuresItemVO().setId(it.getId()).setName(it.getName()).setItems(Collections.emptyList()));
} else {