需求
ERP的審批流,每個審批存在多個審批節點,每個節點下有N個領導的評論以及意見,針對每個審批評論的已讀未讀,需要設置
難點
貌似難點也不是很多,針對已讀/未讀的解決方案網上成熟的方案也不少
說明
點擊查看評論: 審批的評論設置爲已讀
新增了一個評論:除評論人以外,所有人對該審批的評論標識都設置爲未讀
項目環境
3個服務一同運行,共享一個reids服務器
解決思路
利用redis對每個用戶每個審批設置布爾值的key-value
核心代碼
private RedisTemplate<String, Boolean> redisTemplate;
@WebLog(operationType = AdminOperationType.QUERY, operationName = "讀某個審批的評論")
@GetMapping("get_audits")
public List<WaitApprovalGroupDto> getAudits() {
List<WaitApprovalGroupDto> audits = queryCommentList();
ValueOperations<String, Boolean> ops = redisTemplate.opsForValue();
audits.parallelStream().forEachOrdered(vo -> {
String key = StringUtils.join("audit::comment::" + vo.getUserId(), "_", vo.getAuditId());
Boolean flag = ops.get(key) == null ? true : ops.get(key);
vo.setHasNewComment(flag);
});
return audits;
}
@WebLog(operationType = AdminOperationType.QUERY, operationName = "讀某個審批的評論")
@GetMapping("read_comment")
public void redisRead(@RequestParam(value = "user_id") Long userId, @RequestParam(value = "audit_id") Long auditId) {
String key = StringUtils.join("audit::comment::" + userId, "_", auditId);
ValueOperations<String, Boolean> ops = redisTemplate.opsForValue();
ops.set(key, false);
}
@WebLog(operationType = AdminOperationType.QUERY, operationName = "添加某個審批的評論")
@GetMapping("add_comment")
public void redisAdd(@RequestParam(value = "user_id") Long userId, @RequestParam(value = "audit_id") Long auditId) {
String key = StringUtils.join("audit::comment::" + userId, "_", auditId);
ValueOperations<String, Boolean> ops = redisTemplate.opsForValue();
// 更新當用戶評論的緩存狀態
ops.set(key, false);
// 將所有涉及的審批的用戶已讀緩存更新爲未讀
queryCommentList().stream()
.filter(vo -> !vo.getUserId().equals(userId))
.forEach(vo -> {
String userKey = StringUtils.join("audit::comment::" + vo.getUserId(), "_", auditId);
ops.set(userKey, true);
});
}
/**
* 模擬所有用戶的審批評論信息查詢
*/
private List<WaitApprovalGroupDto> queryCommentList() {
List<WaitApprovalGroupDto> lists = Lists.newArrayList();
WaitApprovalGroupDto dto = new WaitApprovalGroupDto();
dto.setId(1L);
dto.setAuditId(1L);
dto.setUserId(1L);
dto.setName("審批1");
WaitApprovalGroupDto dto2 = new WaitApprovalGroupDto();
dto2.setId(2L);
dto2.setUserId(2L);
dto2.setAuditId(2L);
dto2.setName("審批2");
WaitApprovalGroupDto dto3 = new WaitApprovalGroupDto();
dto3.setId(3L);
dto3.setUserId(3L);
dto3.setAuditId(3L);
dto3.setName("審批3");
WaitApprovalGroupDto dto4 = new WaitApprovalGroupDto();
BeanUtils.copyProperties(dto, dto4);
dto4.setAuditId(2L);
WaitApprovalGroupDto dto5 = new WaitApprovalGroupDto();
BeanUtils.copyProperties(dto, dto5);
dto5.setAuditId(3L);
WaitApprovalGroupDto dto6 = new WaitApprovalGroupDto();
BeanUtils.copyProperties(dto2, dto6);
dto6.setAuditId(2L);
WaitApprovalGroupDto dto7 = new WaitApprovalGroupDto();
BeanUtils.copyProperties(dto2, dto7);
dto7.setAuditId(3L);
WaitApprovalGroupDto dto8 = new WaitApprovalGroupDto();
BeanUtils.copyProperties(dto3, dto8);
dto8.setAuditId(2L);
WaitApprovalGroupDto dto9 = new WaitApprovalGroupDto();
BeanUtils.copyProperties(dto3, dto9);
dto9.setAuditId(3L);
lists.add(dto);
lists.add(dto2);
lists.add(dto3);
lists.add(dto4);
lists.add(dto5);
lists.add(dto6);
lists.add(dto7);
lists.add(dto8);
lists.add(dto9);
lists.sort(Comparator.comparing(WaitApprovalGroupDto::getUserId)
.thenComparing(WaitApprovalGroupDto::getAuditId));
return lists;
}
package com.micecs.erp.module.meeting.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.micecs.erp.module.enums.ApprovalStageEnum;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author simengyuan, [email protected]
* @version 1.0
*/
@Data
public class WaitApprovalGroupDto {
private Long id;
private String name;
private Long auditId;
private Boolean hasNewComment;
private Long userId;
}
過期時間記得加上,opts.expire(30, TimeUnit.Days);