flow back up

This commit is contained in:
yanglin 2024-12-30 18:15:37 +08:00
parent 3634dfcd20
commit 6d151429af
27 changed files with 511 additions and 465 deletions

View File

@ -1,78 +0,0 @@
package cn.axzo.msg.center.event.card;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.msg.center.api.mq.CardPresetButtonPressedMessage;
import cn.axzo.msg.center.message.service.todo.TodoWithCardWrapper;
import cn.axzo.msg.center.message.service.todo.manage.TodoManager;
import cn.axzo.msg.center.notices.common.constans.CommonConstants;
import cn.axzo.msg.center.service.enums.MqMessageType;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* @author xudawei@axzo.cn
* @date 2024/11/07
* @desc 卡片预设MQ消费
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class CardChangeStateSyncTodoEventHandler implements EventHandler, InitializingBean {
private final EventConsumer eventConsumer;
private final TodoWithCardWrapper todoWithCardWrapper;
private final TodoManager todoManager;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (!MqMessageType.CARD_PRESET_BUTTON_PRESSED.getEventName().equalsIgnoreCase(event.getEventCode().getName())) {
return;
}
log.info("CardChangeStateSyncTodoEventHandler-start - handle mq event, event={}", JSON.toJSONString(event));
try {
long start = System.currentTimeMillis();
handleMqMessage(event);
long end = System.currentTimeMillis();
log.warn("CardChangeStateSyncTodoEventHandler-handle mq event, used={}ms, event={}", end - start, JSON.toJSONString(event));
} catch (Exception e) {
log.warn("CardChangeStateSyncTodoEventHandler-error - handle mq event, event={}", JSON.toJSONString(event), e);
}
}
/**
* 业务逻辑
*/
private void handleMqMessage(Event event) {
//解析数据
CardPresetButtonPressedMessage payload = event.normalizedData(CardPresetButtonPressedMessage.class);
if (Objects.isNull(payload)) {
return;
}
if (Objects.isNull(payload.getCardInfo())) {
return;
}
if (!CommonConstants.TODO_SYSN_CARD_APP_CODE.equalsIgnoreCase(payload.getCardInfo().getAppCode())) {
return;
}
Long operatorId = Objects.nonNull(payload.getOperatorId()) ? payload.getOperatorId() : 0L;
todoWithCardWrapper.fireTodoWhenPresetButtonPressedByCard(todoManager, payload.getPresetButtonType(), payload.getCardInfo(), operatorId);
}
@Override
public void afterPropertiesSet() {
Event.EventCode eventCode = new Event.EventCode(MqMessageType.CARD_PRESET_BUTTON_PRESSED.getEventModel(), MqMessageType.CARD_PRESET_BUTTON_PRESSED.getEventName());
eventConsumer.registerHandler(eventCode, this);
}
}

View File

@ -295,15 +295,9 @@ public class PendingMessageNewController implements PendingMessageClient {
} }
@Override @Override
@Deprecated
public CommonResponse<Boolean> setHide(SetHideRequest req) { public CommonResponse<Boolean> setHide(SetHideRequest req) {
log.info("setHide, request={}", JSON.toJSONString(req)); return CommonResponse.success(true);
Boolean response = null;
try {
response = todoManager.setHide(req);
return CommonResponse.success(response);
} finally {
log.info("setHide. request={}, response={}", req, response);
}
} }
@Override @Override

View File

@ -29,7 +29,6 @@ import cn.axzo.msg.center.service.pending.card.domain.CardButtonStates;
import cn.axzo.msg.center.service.pending.request.CardPresetButtonPressedRequest; import cn.axzo.msg.center.service.pending.request.CardPresetButtonPressedRequest;
import cn.axzo.msg.center.service.pending.request.CardPresetButtonRequest; import cn.axzo.msg.center.service.pending.request.CardPresetButtonRequest;
import cn.axzo.msg.center.service.pending.request.CardSendRequest; import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdatePresetButtonRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdateRequest; import cn.axzo.msg.center.service.pending.request.CardUpdateRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdateStateRequest; import cn.axzo.msg.center.service.pending.request.CardUpdateStateRequest;
import cn.axzo.msg.center.service.pending.request.ResendMessageRequest; import cn.axzo.msg.center.service.pending.request.ResendMessageRequest;
@ -138,11 +137,9 @@ public class CardManager {
public void updateState(CardUpdateStateRequest request) { public void updateState(CardUpdateStateRequest request) {
request.validate(); request.validate();
TemplateModelV3 templateModel = cardSupport.ensureImChannelPresent(request.getTemplateCode()); TemplateModelV3 templateModel = cardSupport.ensureImChannelPresent(request.getTemplateCode());
boolean updated = false;
// 不要放到for里面去了 // 不要放到for里面去了
CardRequestContext<CardUpdateStateRequest> requestContext = CardRequestContext.create(request); CardRequestContext<CardUpdateStateRequest> requestContext = CardRequestContext.create(request);
for (List<Card> cards : cardsCursor(request)) { for (List<Card> cards : cardsCursor(request)) {
updated = true;
UpdateExecutor executor = new UpdateExecutor(requestContext, "updateState", templateModel, cards); UpdateExecutor executor = new UpdateExecutor(requestContext, "updateState", templateModel, cards);
executor.update(card -> { executor.update(card -> {
Card update = executor.createUpdate(card); Card update = executor.createUpdate(card);
@ -151,10 +148,9 @@ public class CardManager {
update.setBizState(request.getBizState()); update.setBizState(request.getBizState());
}); });
} }
BizAssertions.assertTrue(updated, "未找到任何需要更新的卡片, request={}", request);
} }
void setActionPerformed(SetActionPerformedRequest request) { public void setActionPerformed(SetActionPerformedRequest request) {
TemplateModelV3 templateModel = cardSupport.ensureImChannelPresent(request.getTemplateCode()); TemplateModelV3 templateModel = cardSupport.ensureImChannelPresent(request.getTemplateCode());
MessageTemplateButtonV3 button = templateModel.findButton(request.getButtonCode()).orElse(null); MessageTemplateButtonV3 button = templateModel.findButton(request.getButtonCode()).orElse(null);
BizAssertions.assertNotNull(button, "找不到对应的按钮. buttonCode={}", request.getButtonCode()); BizAssertions.assertNotNull(button, "找不到对应的按钮. buttonCode={}", request.getButtonCode());
@ -180,13 +176,6 @@ public class CardManager {
"卡片已是终状态, 无法'{}'", request.getPresetButtonType().getDesc()); "卡片已是终状态, 无法'{}'", request.getPresetButtonType().getDesc());
} }
public void firePresetButtonPressed(CardUpdatePresetButtonRequest request) {
TemplateModelV3 templateModel = cardSupport.ensureImChannelPresent(request.getTemplateCode());
CardRequestContext<CardUpdatePresetButtonRequest> requestContext = CardRequestContext.create(request);
for (List<Card> cards : cardsCursor(request))
firePresetButtonPressedImpl(request, requestContext, templateModel, cards);
}
private UpdateStateResult firePresetButtonPressedImpl( private UpdateStateResult firePresetButtonPressedImpl(
CardPresetButtonRequest request, CardRequestContext<?> requestContext, CardPresetButtonRequest request, CardRequestContext<?> requestContext,
TemplateModelV3 templateModel, List<Card> cards) { TemplateModelV3 templateModel, List<Card> cards) {

View File

@ -163,6 +163,12 @@ class CardParser {
return bizBody; return bizBody;
} }
private boolean isPerformActionAvailable(ParsedButtonV3 button) {
if (cardProps.getPerformActionSystemButtonCodes().contains(button.getCode()))
return true;
return button.isPerformActionAvailable();
}
private static List<AppLink> getNativeAppLinks(UrlConfig urlConfig) { private static List<AppLink> getNativeAppLinks(UrlConfig urlConfig) {
if (urlConfig == null) return Collections.emptyList(); if (urlConfig == null) return Collections.emptyList();
NativeAppLinkUrlConfigVisitor visitor = new NativeAppLinkUrlConfigVisitor(); NativeAppLinkUrlConfigVisitor visitor = new NativeAppLinkUrlConfigVisitor();

View File

@ -1,5 +1,6 @@
package cn.axzo.msg.center.message.service.card; package cn.axzo.msg.center.message.service.card;
import com.google.common.collect.Sets;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.context.config.annotation.RefreshScope;
@ -23,6 +24,7 @@ public class CardProps {
private boolean enableCardIdempotent = true; private boolean enableCardIdempotent = true;
private int updateCardBatchSize = 200; private int updateCardBatchSize = 200;
private Set<String> idempotentFreeTemplateCodes = new HashSet<>(); private Set<String> idempotentFreeTemplateCodes = new HashSet<>();
private Set<String> performActionSystemButtonCodes = Sets.newHashSet("");
boolean isIdempotentFree(String templateCode) { boolean isIdempotentFree(String templateCode) {
return getIdempotentFreeTemplateCodes().contains(templateCode); return getIdempotentFreeTemplateCodes().contains(templateCode);

View File

@ -1,6 +1,5 @@
package cn.axzo.msg.center.message.service.card; package cn.axzo.msg.center.message.service.card;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.framework.jackson.utility.JSON; import cn.axzo.framework.jackson.utility.JSON;
import cn.axzo.im.center.api.vo.PersonAccountAttribute; import cn.axzo.im.center.api.vo.PersonAccountAttribute;
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam; import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
@ -15,6 +14,7 @@ import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.message.domain.vo.GeneralMessagePushVO; import cn.axzo.msg.center.message.domain.vo.GeneralMessagePushVO;
import cn.axzo.msg.center.message.service.card.domain.CardGroup; import cn.axzo.msg.center.message.service.card.domain.CardGroup;
import cn.axzo.msg.center.message.service.card.domain.CardSendModel; import cn.axzo.msg.center.message.service.card.domain.CardSendModel;
import cn.axzo.msg.center.message.service.card.exception.CardIdempotentException;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Parser; import cn.axzo.msg.center.message.service.impl.v3.ModelV3Parser;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service; import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service;
import cn.axzo.msg.center.message.service.impl.v3.UrlParser; import cn.axzo.msg.center.message.service.impl.v3.UrlParser;
@ -82,7 +82,7 @@ public class CardSupport {
cardIdempotentDao.save(idempotent); cardIdempotentDao.save(idempotent);
} catch (DuplicateKeyException e) { } catch (DuplicateKeyException e) {
log.warn("重复创建卡片, request={}", request); log.warn("重复创建卡片, request={}", request);
throw new ServiceException(String.format("重复创建卡片: %s", idempotent)); throw new CardIdempotentException(String.format("重复创建卡片: %s", idempotent));
} }
} }

View File

@ -0,0 +1,14 @@
package cn.axzo.msg.center.message.service.card.exception;
import cn.axzo.basics.common.exception.ServiceException;
/**
* @author yanglin
*/
public class CardIdempotentException extends ServiceException {
public CardIdempotentException(String msg) {
super(msg);
}
}

View File

@ -1,281 +0,0 @@
package cn.axzo.msg.center.message.service.todo;
import cn.axzo.msg.center.api.mq.CardInfo;
import cn.axzo.msg.center.dal.TodoDao;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
import cn.axzo.msg.center.message.service.card.CardManager;
import cn.axzo.msg.center.message.service.todo.manage.TodoLogger;
import cn.axzo.msg.center.message.service.todo.manage.TodoManager;
import cn.axzo.msg.center.message.service.todo.manage.TodoRequestContext;
import cn.axzo.msg.center.notices.common.constans.CommonConstants;
import cn.axzo.msg.center.service.dto.PeerPerson;
import cn.axzo.msg.center.service.dto.PersonDTO;
import cn.axzo.msg.center.service.enums.CardBizState;
import cn.axzo.msg.center.service.enums.PresetButtonType;
import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdatePresetButtonRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdateStateRequest;
import cn.axzo.msg.center.service.pending.request.PresetButtonPressedRequest;
import cn.axzo.msg.center.service.util.IdBuilder;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author xudawei@axzo.cn
* @date 2024/12/12
* @desc 待办与卡片关联包装
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class TodoWithCardWrapper {
private final CardManager cardManager;
private final TodoLogger todoLogger;
private final TodoDao todoDao;
/**
* 卡片预设按钮,同步待办
* 卡片预设同步待办状态
* @param presetButtonType 预设类型
* @param cardInfo 卡片
*/
public void fireTodoWhenPresetButtonPressedByCard(TodoManager todoManager, PresetButtonType presetButtonType, CardInfo cardInfo, Long operatorId) {
if (Objects.isNull(presetButtonType) || Objects.isNull(cardInfo)) {
return;
}
if (StringUtils.isBlank(cardInfo.getTemplateCode()) || StringUtils.isBlank(cardInfo.getBizCode())) {
return;
}
log.info("TodoWithCardWrapper#fireTodoWhenPresetButtonPressedByCard start,presetButtonType:{},cardInfo:{}", presetButtonType, JSON.toJSONString(cardInfo));
TodoRequestContext ctx = TodoRequestContext.create("cardPresetTodo", cardInfo);
ctx.addLogContent("presetButtonType", presetButtonType);
ctx.addLogContent("operatorId", operatorId);
//1 查询待办(Todo对象)根据templateCode/bizCode/subBizCode/receiverPresonId/receiverOuId/receiverWorkspaceId 理论上只能查询一条[待办]记录
List<Todo> todoList = todoDao.findByCondition(cardInfo.getTemplateCode(), cardInfo.getBizCode(), cardInfo.getSubBizCode(), cardInfo.getReceiverPersonId(), cardInfo.getReceiverOuId(), cardInfo.getReceiverWorkspaceId());
try {
if (CollectionUtils.isEmpty(todoList)) {
return;
}
//2 同步待办预设状态
for (Todo todo : todoList) {
PresetButtonPressedRequest presetButtonPressedRequest = this.buildPresetButtonPressedRequest(todo.getIdentityCode(), presetButtonType, operatorId);
todoManager.firePresetButtonPressed( presetButtonPressedRequest, false);
ctx.addLogContent("fireTodoWhenPresetButtonPressedByCard", "success");
todoLogger.logTodosUpdated(ctx, Collections.singletonList(todo));
}
} catch (Exception e) {
log.warn("TodoWithCardWrapper#fireTodoWhenPresetButtonPressedByCard exception,presetButtonType:{},cardInfo:{}", presetButtonType, JSON.toJSONString(cardInfo),e);
ctx.addLogContent("exception", Throwables.getStackTraceAsString(e));
todoLogger.logTodosUpdated(ctx, todoList);
}
}
/**
* 构建预设按钮对象
*/
private PresetButtonPressedRequest buildPresetButtonPressedRequest(String identityCode, PresetButtonType presetButtonType, Long operatorId) {
return PresetButtonPressedRequest.builder()
.identityCode(identityCode)
.presetButtonType(presetButtonType)
.operatorId(operatorId)
.build();
}
/**
* 点击预设按钮-同步卡片
* 待办预设同步卡片状态
*/
public void fireCardWhenPresetButtonPressedByTodo(PresetButtonPressedRequest request, Todo todo, boolean isSyncCard) {
//是否同步卡片信息true:同步;false:不同步
if (!isSyncCard) {
return;
}
log.info("TodoWithCardWrapper#fireCardWhenPresetButtonPressedByTodo start,request:{},todo:{}", JSON.toJSONString(request), JSON.toJSONString(todo));
TodoRequestContext ctx = TodoRequestContext.create("todoPresetCard", request);
try {
//1 构建对象
CardUpdatePresetButtonRequest cardRequest = this.buildCardUpdatePresetButtonRequest(request, todo);
//2 同步卡片
cardManager.firePresetButtonPressed(cardRequest);
ctx.addLogContent("fireCardWhenPresetButtonPressedByTodo", "success");
todoLogger.logTodosUpdated(ctx, Collections.singletonList(todo));
} catch (Exception e) {
log.warn("TodoWithCardWrapper#fireCardWhenPresetButtonPressedByTodo exception,request:{},todo:{}", JSON.toJSONString(request), JSON.toJSONString(todo),e);
ctx.addLogContent("exception", Throwables.getStackTraceAsString(e));
todoLogger.logTodosUpdated(ctx, Collections.singletonList(todo));
}
}
/**
* 构建对象
*/
private CardUpdatePresetButtonRequest buildCardUpdatePresetButtonRequest(PresetButtonPressedRequest request, Todo todo) {
CardUpdatePresetButtonRequest cardRequest = new CardUpdatePresetButtonRequest();
cardRequest.setAppCode(CommonConstants.TODO_SYSN_CARD_APP_CODE);
cardRequest.setTemplateCode(todo.getTemplateCode());
cardRequest.setBizCode(todo.getBizCode());
cardRequest.setSubBizCode(todo.getSubBizCode());
cardRequest.setReceivers(Sets.newHashSet(
PeerPerson.newPeerPerson(todo.getExecutorPersonId()
, todo.getOuId()
, todo.getReceiverWorkspaceId())));
cardRequest.setPresetButtonType(request.getPresetButtonType());
cardRequest.setOperatorId(request.getOperatorId());
return cardRequest;
}
/**
* 发送卡片信息
*/
public void send(PendingMessagePushParam param,List<Todo> todos) {
log.info("TodoWithCardWrapper#send start,param:{}", JSON.toJSONString(param));
TodoRequestContext ctx = TodoRequestContext.create("todoSyncCardSend", param);
try {
//1 构建对象
CardSendRequest cardSendRequest = this.buildCardSendRequest(param);
ctx.addLogContent(JSON.toJSONString(cardSendRequest));
//2 发送
cardManager.send(cardSendRequest);
ctx.addLogContent("sendCard", "success");
todoLogger.logTodosUpdated(ctx, todos);
} catch (Exception e) {
log.warn("TodoWithCardWrapper#send,param:{}", JSON.toJSONString(param), e);
ctx.addLogContent("exception", Throwables.getStackTraceAsString(e));
todoLogger.logTodosUpdated(ctx, todos);
}
}
/**
* 卡片更新状态-完成
*/
public void cardCompleteStateByTodoList(List<Todo> todoList) {
this.cardUpdateStateByTodoList(todoList,CardBizState.END, true);
}
/**
* 卡片更新状态-回滚
* 暂时不需要
*/
public void cardRollbackStateByTodoList(List<Todo> todoList) {
this.cardUpdateStateByTodoList(todoList, CardBizState.ABORTED, false);
}
/**
* 卡片更新状态-撤销
*/
public void cardRevokeStateByTodoList(List<Todo> todoList) {
this.cardUpdateStateByTodoList(todoList, CardBizState.REVOKED, false);
}
/**
* 卡片更新状态-执行中
*/
public void cardProcessingStateByTodoList(List<Todo> todoList) {
this.cardUpdateStateByTodoList(todoList, CardBizState.PENDING, false);
}
/**
* 卡片更新完成状态
*/
private void cardUpdateStateByTodoList(List<Todo> todoList, CardBizState bizState, boolean setCardCompleted) {
log.info("TodoWithCardWrapper#cardUpdateStateByTodoList start,todoList:{},bizState:{},setCardCompleted:{}", JSON.toJSONString(todoList), bizState, setCardCompleted);
if (CollectionUtils.isEmpty(todoList)) {
return;
}
TodoRequestContext ctx = TodoRequestContext.create("todoSyncCardState", todoList);
ctx.addLogContent("bizState", bizState);
ctx.addLogContent("cardState", bizState);
ctx.addLogContent("setCardCompleted", setCardCompleted);
try {
for (Todo todo : todoList) {
//1 构建对象
CardUpdateStateRequest updateStateRequest = this.buildCardUpdateStateRequest(todo, bizState, setCardCompleted);
//2 更新状态
cardManager.updateState(updateStateRequest);
ctx.addLogContent("cardUpdateStateByTodoList", "success");
todoLogger.logTodosUpdated(ctx, Collections.singletonList(todo));
}
} catch (Exception e) {
log.warn("TodoWithCardWrapper#cardCompleteState,todoList:{}", JSON.toJSONString(todoList), e);
ctx.addLogContent("exception", Throwables.getStackTraceAsString(e));
todoLogger.logTodosUpdated(ctx, todoList);
}
}
/**
* 构建卡片状态更新对象
*/
private CardUpdateStateRequest buildCardUpdateStateRequest(Todo todo, CardBizState bizState, boolean setCardCompleted) {
CardUpdateStateRequest updateStateRequest = new CardUpdateStateRequest();
updateStateRequest.setBizState(bizState);
updateStateRequest.setCardCompleted(setCardCompleted);
updateStateRequest.setAppCode(CommonConstants.TODO_SYSN_CARD_APP_CODE);
updateStateRequest.setTemplateCode(todo.getTemplateCode());
updateStateRequest.setBizCode(todo.getBizCode());
updateStateRequest.setSubBizCode(todo.getSubBizCode());
updateStateRequest.setReceivers(Sets.newHashSet(PeerPerson.newPeerPerson(todo.getExecutorPersonId(), todo.getOuId(), todo.getReceiverWorkspaceId())));//TODO
return updateStateRequest;
}
/**
* 构建对象
*/
private CardSendRequest buildCardSendRequest(PendingMessagePushParam param) {
CardSendRequest sendRequest = new CardSendRequest();
sendRequest.setAppCode(CommonConstants.TODO_SYSN_CARD_APP_CODE);
sendRequest.setTemplateCode(param.getTemplateCode());
sendRequest.setBizCode(param.getBizCode());
sendRequest.setSubBizCode(param.getSubBizCode());
if (Objects.nonNull(param.getPromoter()) && Objects.nonNull(param.getPromoter().getId())) {
sendRequest.setSender(PeerPerson.newPeerPerson(param.getPromoter().getId()
, Objects.nonNull(param.getPromoterOuId()) ? param.getPromoterOuId() : null
, Objects.nonNull(param.getPromoterWorkspaceId()) ? param.getPromoterWorkspaceId() : null));
}
sendRequest.setReceivers(this.buildReceivers(param.getExecutor(), param.getOuId(), param.getWorkspaceId()));
if (StringUtils.isNotBlank(param.getBizExtParams())) {
sendRequest.setBizParam(JSON.parseObject(param.getBizExtParams()));
}
if (StringUtils.isNotBlank(param.getRouterParams())) {
sendRequest.setRouterParam(JSON.parseObject(param.getRouterParams()));
}
sendRequest.setIdempotentCode(IdBuilder.builder()
.append(param.getBizCode())
.append(param.getSubBizCode())
.build());
return sendRequest;
}
private Set<PeerPerson> buildReceivers(List<PersonDTO> personDTOS, Long ouId, Long workspaceId) {
if (CollectionUtils.isEmpty(personDTOS)) {
return Sets.newHashSet();
}
return personDTOS.stream().map(item -> PeerPerson.newPeerPerson(item.getId(), ouId, workspaceId)).collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,33 @@
package cn.axzo.msg.center.message.service.todo.card;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.msg.center.api.mq.CardPresetButtonPressedMessage;
import cn.axzo.msg.center.service.enums.MqMessageType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Component
@RequiredArgsConstructor
public class CardSyncTodoHandler implements EventHandler, InitializingBean {
private final EventConsumer eventConsumer;
private final TodoSyncCardService todoSyncCardService;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
CardPresetButtonPressedMessage message = event.normalizedData(CardPresetButtonPressedMessage.class);
todoSyncCardService.onCardPresetButtonPressed(message);
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(MqMessageType.CARD_PRESET_BUTTON_PRESSED.getEventCode(), this);
}
}

View File

@ -0,0 +1,38 @@
package cn.axzo.msg.center.message.service.todo.card;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.msg.center.api.mq.TodoUpdateMessage;
import cn.axzo.msg.center.mq.ConsumerIsolation;
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
import cn.axzo.msg.center.service.enums.MqMessageType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Component
@RequiredArgsConstructor
class TodoSyncCardBizHandler implements EventHandler, InitializingBean {
private final EventConsumer eventConsumer;
private final TodoSyncCardService todoSyncCardService;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
TodoUpdateMessage message = event.normalizedData(TodoUpdateMessage.class);
if (ConsumerIsolation.getIsolation() == ConsumerIsolation.TODO_SYNC_CARD_BIZ
&& message.getUpdatedTodo().getBizCategory() == BizCategoryEnum.OTHER) {
todoSyncCardService.onMessage(event, message);
}
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(MqMessageType.TODO_STATE_UPDATE.getEventCode(), this);
}
}

View File

@ -0,0 +1,38 @@
package cn.axzo.msg.center.message.service.todo.card;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.msg.center.api.mq.TodoUpdateMessage;
import cn.axzo.msg.center.mq.ConsumerIsolation;
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
import cn.axzo.msg.center.service.enums.MqMessageType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Component
@RequiredArgsConstructor
class TodoSyncCardFlowHandler implements EventHandler, InitializingBean {
private final EventConsumer eventConsumer;
private final TodoSyncCardService todoSyncCardService;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
TodoUpdateMessage message = event.normalizedData(TodoUpdateMessage.class);
if (ConsumerIsolation.getIsolation() == ConsumerIsolation.TODO_SYNC_CARD_FLOW
&& message.getUpdatedTodo().getBizCategory() == BizCategoryEnum.FLOW) {
todoSyncCardService.onMessage(event, message);
}
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(MqMessageType.TODO_STATE_UPDATE.getEventCode(), this);
}
}

View File

@ -0,0 +1,215 @@
package cn.axzo.msg.center.message.service.todo.card;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.msg.center.api.mq.CardPresetButtonPressedMessage;
import cn.axzo.msg.center.api.mq.TodoUpdateMessage;
import cn.axzo.msg.center.dal.MessageTemplateV3Dao;
import cn.axzo.msg.center.dal.TodoBusinessDao;
import cn.axzo.msg.center.dal.TodoDao;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.domain.entity.TodoBusiness;
import cn.axzo.msg.center.message.service.card.CardManager;
import cn.axzo.msg.center.message.service.card.exception.CardIdempotentException;
import cn.axzo.msg.center.message.service.todo.manage.TodoLogger;
import cn.axzo.msg.center.message.service.todo.manage.TodoManager;
import cn.axzo.msg.center.message.service.todo.manage.TodoRequestContext;
import cn.axzo.msg.center.service.dto.PeerPerson;
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
import cn.axzo.msg.center.service.enums.CardBizState;
import cn.axzo.msg.center.service.enums.MessageChannel;
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
import cn.axzo.msg.center.service.enums.StatusEnum;
import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdateStateRequest;
import cn.axzo.msg.center.service.pending.request.PresetButtonPressedRequest;
import cn.axzo.msg.center.service.pending.request.SetActionPerformedRequest;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Slf4j
@Component
@RequiredArgsConstructor
class TodoSyncCardService {
private static final String TODO_CATEGORY_BIZ_PARAM_KEY = "____todo_category____";
private static final String TODO_IDENTITY_CODE_BIZ_PARAM_KEY = "____todo_identity_code____";
private static final String APP_CODE = "msg-center:todo";
private final TodoDao todoDao;
private final TodoBusinessDao todoBusinessDao;
private final CardManager cardManager;
private final TodoLogger todoLogger;
private final MessageTemplateV3Dao messageTemplateV3Dao;
private final TodoManager todoManager;
void onMessage(Event event, TodoUpdateMessage message) {
log.info("TodoSyncStateToCardService.onMessage: {}", message);
try {
sync(event, message);
} catch (Exception e) {
log.warn("TodoSyncStateToCardService.onMessage: error, message={}", message, e);
throw new RuntimeException(e);
}
}
private void sync(Event event, TodoUpdateMessage message) {
if (!message.isUpdateCard()) {
log.warn("TodoSyncStateToCardService.onMessage: not update card, message={}", message);
return;
}
Todo todo = todoDao.findTodoByCode(message.getUpdatedTodo().getIdentityCode())
.orElse(null);
if (todo == null) {
log.warn("TodoSyncStateToCardService.onMessage: todo not found, message={}", message);
return;
}
MessageTemplateV3 template = messageTemplateV3Dao
.findByCode(todo.getTemplateCode())
.orElse(null);
if (template == null) {
log.warn("TodoSyncStateToCardService.onMessage: template not found, message={}", message);
return;
}
if (template.getStatus() != StatusEnum.ENABLE) {
log.warn("TodoSyncStateToCardService.onMessage: template is disabled, message={}", message);
return;
}
if (!template.determineChannels().contains(MessageChannel.IM)) {
log.warn("TodoSyncStateToCardService.onMessage: template not support IM, message={}", message);
return;
}
TodoBusiness business = todoBusinessDao.getBusinesses(todo).findBusiness(todo).orElse(null);
if (business == null) {
log.warn("TodoSyncStateToCardService.sendCard: business not found, todo={}", todo);
return;
}
if (todo.getState() == PendingMessageStateEnum.HAS_BEEN_SENT
|| todo.getState() == PendingMessageStateEnum.CREATED) {
sendCard(event, business, todo);
} else {
updateCardState(event, business, todo);
if (business.getBizCategory() == BizCategoryEnum.FLOW)
updateFlowButtonStates(event, business, todo);
}
}
private void sendCard(Event event, TodoBusiness business, Todo todo) {
CardSendRequest request = new CardSendRequest();
request.setAppCode(APP_CODE);
request.setTemplateCode(todo.getTemplateCode());
request.setBizCode(todo.getBizCode());
request.setIdempotentCode(todo.getIdentityCode());
request.setSubBizCode(todo.getSubBizCode());
request.setSender(PeerPerson.create(business.getPromoterPersonId(), business.getOuId(), business.getOrgId()));
request.setReceivers(Sets.newHashSet(PeerPerson.create(
todo.getExecutorPersonId(), todo.getOuId(), todo.getOrgId())));
JSONObject bizParam = todo.bizParam();
bizParam.put(TODO_CATEGORY_BIZ_PARAM_KEY, business.getBizCategory().getCode());
bizParam.put(TODO_IDENTITY_CODE_BIZ_PARAM_KEY, todo.getIdentityCode());
request.setBizParam(bizParam);
request.setRouterParam(todo.routerParam());
request.setReturnCards(false);
try {
log.info("TodoSyncStateToCardService.sendCard: todo={}", todo);
cardManager.send(request);
TodoRequestContext ctx = TodoRequestContext
.create("sendCard", event)
.addLogContent("sendCardRequest", request);
todoLogger.logTodoUpdated(ctx, todo);
log.info("TodoSyncStateToCardService.sendCard: success, todo={}", todo);
} catch (CardIdempotentException ignored) {
log.warn("TodoSyncStateToCardService.sendCard: idempotent, todo={}", todo);
}
}
private void updateCardState(Event event, TodoBusiness business, Todo todo) {
CardUpdateStateRequest request = new CardUpdateStateRequest();
request.setAppCode(APP_CODE);
request.setTemplateCode(todo.getTemplateCode());
request.setBizCode(todo.getBizCode());
request.setSubBizCode(todo.getSubBizCode());
request.setReceivers(Sets.newHashSet(PeerPerson.create(
todo.getExecutorPersonId(), todo.getOuId(), todo.getOrgId())));
request.setBizState(getBizState(business, todo));
request.setCardCompleted(todo.getState() == PendingMessageStateEnum.COMPLETED);
TodoRequestContext ctx = TodoRequestContext
.create("updateCardState", event)
.addLogContent("updateCardStateRequest", request)
.addLogContent("todo", todo);
if (request.isValid()) {
cardManager.updateState(request);
todoLogger.logTodoUpdated(
ctx.copy().addLogContent("updateCardStateResult", "success"),
todo);
} else {
log.info("TodoSyncStateToCardService.updateCardState: invalid request, todo={}", todo);
todoLogger.logTodoUpdated(
ctx.copy().addLogContent("updateCardStateResult", "invalid update card state request"),
todo);
}
}
private void updateFlowButtonStates(Event event, TodoBusiness business, Todo todo) {
if (business.getBizFinalState() == null || !business.getBizFinalState().isEnableActionPerformed()) {
log.warn("TodoSyncStateToCardService.updateFlowButtonStates:" +
" bizFinalState is null or not action performable, business={}, todo={}", business, todo);
return;
}
SetActionPerformedRequest request = new SetActionPerformedRequest();
request.setAppCode(APP_CODE);
request.setTemplateCode(todo.getTemplateCode());
request.setBizCode(todo.getBizCode());
request.setSubBizCode(todo.getSubBizCode());
request.setReceivers(Sets.newHashSet(PeerPerson.create(
todo.getExecutorPersonId(), todo.getOuId(), todo.getOrgId())));
request.setButtonCode(business.getBizFinalState().getButtonCode());
request.setCardBizState(getBizState(business, todo));
cardManager.setActionPerformed(request);
TodoRequestContext ctx = TodoRequestContext
.create("updateCardFlowButtonStates", event)
.addLogContent("todo", todo);
todoLogger.logTodoUpdated(ctx, todo);
}
private CardBizState getBizState(TodoBusiness business, Todo todo) {
if (business.getBizCategory() == BizCategoryEnum.OTHER) {
if (todo.getState() == PendingMessageStateEnum.COMPLETED)
return CardBizState.COMPLETED;
if (todo.getState() == PendingMessageStateEnum.PROCESSING)
return CardBizState.IN_PROGRESS;
if (todo.getState() == PendingMessageStateEnum.RETRACT)
return CardBizState.REVOKED;
return null;
}
if (business.getBizFinalState() == BizFinalStateEnum.COMPLETED)
return CardBizState.COMPLETED;
if (business.getBizFinalState() == BizFinalStateEnum.RETRACT)
return CardBizState.REVOKED;
if (business.getBizFinalState() == BizFinalStateEnum.PASSED)
return CardBizState.AGREED;
if (business.getBizFinalState() == BizFinalStateEnum.REJECTED)
return CardBizState.REJECTED;
if (business.getBizFinalState() == BizFinalStateEnum.ABORTED)
return CardBizState.ABORTED;
return null;
}
void onCardPresetButtonPressed(CardPresetButtonPressedMessage message) {
log.info("TodoSyncStateToCardService.onCardPresetButtonPressed: {}", message);
if(!APP_CODE.equals(message.getCardInfo().getAppCode())) {
log.info("TodoSyncStateToCardService.onCardPresetButtonPressed: not msg-center:todo, message={}", message);
return;
}
PresetButtonPressedRequest request = new PresetButtonPressedRequest();
todoManager.firePresetButtonPressed(request, false);
}
}

View File

@ -55,7 +55,7 @@ public class TodoLogger {
logTodosUpdated(ctx, todos); logTodosUpdated(ctx, todos);
} }
void logTodoUpdated(TodoRequestContext ctx, Todo todo) { public void logTodoUpdated(TodoRequestContext ctx, Todo todo) {
logTodosUpdated(ctx, Collections.singletonList(todo)); logTodosUpdated(ctx, Collections.singletonList(todo));
} }

View File

@ -18,7 +18,6 @@ import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3; import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam; import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service; import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service;
import cn.axzo.msg.center.message.service.todo.TodoWithCardWrapper;
import cn.axzo.msg.center.message.service.todo.manage.broadcast.TodoBroadcaster; import cn.axzo.msg.center.message.service.todo.manage.broadcast.TodoBroadcaster;
import cn.axzo.msg.center.message.service.todo.manage.broadcast.TodoMqBroadcaster; import cn.axzo.msg.center.message.service.todo.manage.broadcast.TodoMqBroadcaster;
import cn.axzo.msg.center.message.service.todo.manage.event.HandoverEvent; import cn.axzo.msg.center.message.service.todo.manage.event.HandoverEvent;
@ -39,13 +38,11 @@ import cn.axzo.msg.center.service.pending.request.CompletePendingMessageRequest;
import cn.axzo.msg.center.service.pending.request.PresetButtonPressedRequest; import cn.axzo.msg.center.service.pending.request.PresetButtonPressedRequest;
import cn.axzo.msg.center.service.pending.request.RevokeByTemplateCodeRequest; import cn.axzo.msg.center.service.pending.request.RevokeByTemplateCodeRequest;
import cn.axzo.msg.center.service.pending.request.RevokePendingMessageByIdRequest; import cn.axzo.msg.center.service.pending.request.RevokePendingMessageByIdRequest;
import cn.axzo.msg.center.service.pending.request.SetHideRequest;
import cn.axzo.msg.center.service.pending.request.TodoHandoverRequest; import cn.axzo.msg.center.service.pending.request.TodoHandoverRequest;
import cn.axzo.msg.center.service.pending.request.UpdateBusinessFinalBizStateRequest; import cn.axzo.msg.center.service.pending.request.UpdateBusinessFinalBizStateRequest;
import cn.axzo.msg.center.service.pending.request.UpdatePendingMessageByIdRequest; import cn.axzo.msg.center.service.pending.request.UpdatePendingMessageByIdRequest;
import cn.axzo.msg.center.service.pending.response.PushPendingMessageDTO; import cn.axzo.msg.center.service.pending.response.PushPendingMessageDTO;
import cn.axzo.msg.center.service.util.JSONUtils; import cn.axzo.msg.center.service.util.JSONUtils;
import cn.axzo.msg.center.utils.DateFormatUtil;
import cn.axzo.msg.center.utils.QueryFormatter; import cn.axzo.msg.center.utils.QueryFormatter;
import cn.axzo.msg.center.utils.UUIDUtil; import cn.axzo.msg.center.utils.UUIDUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
@ -59,7 +56,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.DuplicateKeyException;
@ -69,7 +65,6 @@ import org.springframework.transaction.support.TransactionTemplate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -100,7 +95,6 @@ public class TodoManager {
private final ApplicationContext applicationContext; private final ApplicationContext applicationContext;
private final TodoBroadcaster todoBroadcaster; private final TodoBroadcaster todoBroadcaster;
private final TransactionTemplate transactionTemplate; private final TransactionTemplate transactionTemplate;
private final TodoWithCardWrapper todoWithCardWrapper;
public List<PushPendingMessageDTO> send(PendingMessagePushParam request) { public List<PushPendingMessageDTO> send(PendingMessagePushParam request) {
TodoRequestContext ctx = TodoRequestContext.create("send", request.normalize()); TodoRequestContext ctx = TodoRequestContext.create("send", request.normalize());
@ -170,7 +164,7 @@ public class TodoManager {
if (StringUtils.isBlank(business.getSampleTodoCode()) if (StringUtils.isBlank(business.getSampleTodoCode())
&& request.determineTodoType() == TodoType.EXECUTABLE) && request.determineTodoType() == TodoType.EXECUTABLE)
todoBusinessDao.updateSampleTodCode(business.getId(), sample.getIdentityCode()); todoBusinessDao.updateSampleTodCode(business.getId(), sample.getIdentityCode());
todoBroadcaster.fireTodoUpdates("send", todos); todoBroadcaster.fireTodoUpdates("send", todos, true);
// 记录日志 // 记录日志
// @formatter:off // @formatter:off
ctx.addLogContent("templateTitle", templateModel.getTemplate().getTitle()) ctx.addLogContent("templateTitle", templateModel.getTemplate().getTitle())
@ -186,7 +180,6 @@ public class TodoManager {
todoLogger.logBusinessUpdated(ctx, business); todoLogger.logBusinessUpdated(ctx, business);
todoLogger.logTodosUpdated(ctx, todos); todoLogger.logTodosUpdated(ctx, todos);
applicationContext.publishEvent(new NewTodoEvent(this, templateModel, todos)); applicationContext.publishEvent(new NewTodoEvent(this, templateModel, todos));
todoWithCardWrapper.send(request, todos);
return todos.stream() return todos.stream()
.map(todo -> new PushPendingMessageDTO( .map(todo -> new PushPendingMessageDTO(
@ -250,8 +243,8 @@ public class TodoManager {
destTodo.setExecutorName(request.determineToPersonName()); destTodo.setExecutorName(request.determineToPersonName());
} }
todoDao.saveBatch(destTodos); todoDao.saveBatch(destTodos);
todoBroadcaster.fireTodoUpdates("handover", srcTodos); todoBroadcaster.fireTodoUpdates("handover", srcTodos, true);
todoBroadcaster.fireTodoUpdates("handover", destTodos); todoBroadcaster.fireTodoUpdates("handover", destTodos, true);
// build handover mappings // build handover mappings
List<TodoHandoverMapping> mappings = new ArrayList<>(); List<TodoHandoverMapping> mappings = new ArrayList<>();
for (int i = 0; i < srcTodos.size(); i++) { for (int i = 0; i < srcTodos.size(); i++) {
@ -285,7 +278,6 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardCompleteStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -296,7 +288,9 @@ public class TodoManager {
public boolean completeById(CompletePendingMessageByIdRequest request) { public boolean completeById(CompletePendingMessageByIdRequest request) {
Set<Long> ids = request.determineIds(); Set<Long> ids = request.determineIds();
BizAssertions.assertNotEmpty(ids, "待办id不能为空"); BizAssertions.assertNotEmpty(ids, "待办id不能为空");
TodoRequestContext ctx = TodoRequestContext.create("completeById", request); TodoRequestContext ctx = TodoRequestContext
.create("completeById", request)
.delayBroadcast(true);
StateAdvanceResult advanceResult = advanceState(ctx, execAdvanceBuilder() StateAdvanceResult advanceResult = advanceState(ctx, execAdvanceBuilder()
.in(Todo::getId, ids.toArray(new Object[0])) .in(Todo::getId, ids.toArray(new Object[0]))
.set(Todo::getState, PendingMessageStateEnum.COMPLETED)); .set(Todo::getState, PendingMessageStateEnum.COMPLETED));
@ -312,7 +306,7 @@ public class TodoManager {
} }
if (advanceResult.isAdvanced()) { if (advanceResult.isAdvanced()) {
todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardCompleteStateByTodoList(advanceResult.getAdvancedTodos()); todoBroadcaster.fireTodoUpdates("completeById", advanceResult.getBusinessId(), true);
} }
return advanceResult.isAdvanced() || businessUpdated; return advanceResult.isAdvanced() || businessUpdated;
@ -341,11 +335,10 @@ public class TodoManager {
todoLogger.logBusinessUpdated(ctx, advanceResult.getBusiness()); todoLogger.logBusinessUpdated(ctx, advanceResult.getBusiness());
} }
if (advanceResult.isAdvanced()) { if (advanceResult.isAdvanced()) {
todoBroadcaster.fireTodoUpdates("completeByBizCode", advanceResult.getBusinessId(), true);
todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardCompleteStateByTodoList(advanceResult.getAdvancedTodos());
} }
advanceResult.broadcast();
return advanceResult.isAdvanced() || businessUpdated; return advanceResult.isAdvanced() || businessUpdated;
} }
@ -384,8 +377,7 @@ public class TodoManager {
TodoRequestContext ctx = TodoRequestContext.create("updateBusinessFinalBizState", request) TodoRequestContext ctx = TodoRequestContext.create("updateBusinessFinalBizState", request)
.addLogContent("updated", updated); .addLogContent("updated", updated);
todoLogger.logBusinessUpdated(ctx, business); todoLogger.logBusinessUpdated(ctx, business);
List<Todo> todos = todoDao.getByBusinessIds(Collections.singletonList(business.getId())); todoBroadcaster.fireTodoUpdates("updateBusinessFinalBizState", business.getId(), true);
todoBroadcaster.fireTodoUpdates("updateBusinessFinalBizState", todos);
} }
return updated; return updated;
} }
@ -404,7 +396,6 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoCompleted(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardCompleteStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -423,8 +414,7 @@ public class TodoManager {
return false; return false;
} }
todoLogger.logTodoRollback(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoRollback(ctx, advanceResult.getAdvancedTodos());
todoBroadcaster.fireTodoUpdates("rollbackBySubBizCode", advanceResult.getAdvancedTodos()); todoBroadcaster.fireTodoUpdates("rollbackBySubBizCode", advanceResult.getAdvancedTodos(), true);
// todoWithCardWrapper.cardRollbackStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -444,7 +434,6 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardRevokeStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -460,7 +449,6 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardRevokeStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -476,7 +464,6 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardRevokeStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -493,7 +480,6 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardRevokeStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
@ -506,37 +492,11 @@ public class TodoManager {
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
return false; return false;
todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos()); todoLogger.logTodoRevoked(ctx, advanceResult.getAdvancedTodos());
todoWithCardWrapper.cardRevokeStateByTodoList(advanceResult.getAdvancedTodos());
return true; return true;
} }
// !! update // !! update
/**
* 将待办设置为隐藏, 隐藏有时间期限
*/
@Transactional(rollbackFor = Exception.class)
public boolean setHide(SetHideRequest request) {
BizAssertions.assertTrue(StringUtils.isNotBlank(request.getSubBizCode()), "subBizCode不能为空");
List<Todo> todos = todoDao.getBySubBizCode(request.getSubBizCode());
if (todos.isEmpty())
return false;
int seconds = request.getHideSeconds() == null
? cfg.getPendingSetHideSeconds() : request.getHideSeconds();
Date expireTime = DateTime.now().plusSeconds(seconds).toDate();
boolean updated = todoDao.setExecutableHide(request.getSubBizCode(), expireTime);
if (updated) {
List<Todo> updatedTodos = todos.stream()
.filter(todo -> todo.getState() == PendingMessageStateEnum.HAS_BEEN_SENT)
.collect(toList());
TodoRequestContext ctx = TodoRequestContext.create("setHide", request)
.addLogContent("expiredTime", expireTime.getTime())
.addLogContent("readableExpiredTime", DateFormatUtil.toReadableString(expireTime));
todoLogger.logTodosUpdated(ctx, updatedTodos);
}
return updated;
}
/** /**
* 将待办设置为执行中 * 将待办设置为执行中
*/ */
@ -557,8 +517,7 @@ public class TodoManager {
request.put("subBizCodes", subBizCodes); request.put("subBizCodes", subBizCodes);
TodoRequestContext ctx = TodoRequestContext.create("batchSetProcessing", request); TodoRequestContext ctx = TodoRequestContext.create("batchSetProcessing", request);
todoLogger.logSetTodoProcessing(ctx, todos); todoLogger.logSetTodoProcessing(ctx, todos);
todoBroadcaster.fireTodoUpdates("batchSetProcessing", todos); todoBroadcaster.fireTodoUpdates("batchSetProcessing", todos, true);
todoWithCardWrapper.cardProcessingStateByTodoList(todos);
} }
return updated; return updated;
} }
@ -595,7 +554,6 @@ public class TodoManager {
.addLogContent("updatedRouterParam", routerParam) .addLogContent("updatedRouterParam", routerParam)
.addLogContent("updatedTemplateCode", request.getTemplateCode()); .addLogContent("updatedTemplateCode", request.getTemplateCode());
todoLogger.logBusinessUpdated(ctx, business); todoLogger.logBusinessUpdated(ctx, business);
//TODO todoWithCardWrapper.send
} }
return updated; return updated;
} }
@ -606,12 +564,14 @@ public class TodoManager {
* 点击预设按钮 * 点击预设按钮
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean firePresetButtonPressed(PresetButtonPressedRequest request, boolean isSyncCard) { public boolean firePresetButtonPressed(PresetButtonPressedRequest request, boolean syncCardState) {
Todo todo = todoDao.findTodoByCode(request.getIdentityCode()).orElse(null); Todo todo = todoDao.findTodoByCode(request.getIdentityCode()).orElse(null);
if (todo == null) if (todo == null)
return false; return false;
TodoRequestContext ctx = TodoRequestContext.create("firePresetButtonPressed", request) TodoRequestContext ctx = TodoRequestContext.create("firePresetButtonPressed", request)
.addLogContent("presetButtonType", request.getPresetButtonType()); .addLogContent("presetButtonType", request.getPresetButtonType());
if (!syncCardState)
ctx.disableUpdateCard();
StateAdvanceResult advanceResult = advanceState(ctx, execAdvanceBuilder() StateAdvanceResult advanceResult = advanceState(ctx, execAdvanceBuilder()
.eq(Todo::getIdentityCode, request.getIdentityCode()) .eq(Todo::getIdentityCode, request.getIdentityCode())
.set(Todo::getState, PendingMessageStateEnum.COMPLETED)); .set(Todo::getState, PendingMessageStateEnum.COMPLETED));
@ -620,8 +580,7 @@ public class TodoManager {
// 支持重复发mq消息 // 支持重复发mq消息
if (isAdvancedOrCompleted) { if (isAdvancedOrCompleted) {
sendMqMessageOnPresetButtonPressed(ctx, request, todo); sendMqMessageOnPresetButtonPressed(ctx, request, todo);
todoBroadcaster.fireTodoUpdates("presetButtonPressed", todo); todoBroadcaster.fireTodoUpdates("presetButtonPressed", todo, syncCardState);
todoWithCardWrapper.fireCardWhenPresetButtonPressedByTodo(request, todo,isSyncCard);
// 如果不是重复发送, 就只记一条日志. 如果是重复发送, 就单独记录一条日志 // 如果不是重复发送, 就只记一条日志. 如果是重复发送, 就单独记录一条日志
if (!advanceResult.isAdvanced()) if (!advanceResult.isAdvanced())
@ -678,6 +637,7 @@ public class TodoManager {
return false; return false;
ImmutableMap<String, Object> request = ImmutableMap.of("personId", personId, "identityCode", identityCode); ImmutableMap<String, Object> request = ImmutableMap.of("personId", personId, "identityCode", identityCode);
TodoRequestContext ctx = TodoRequestContext.create("setCopiedToMeRead", request) TodoRequestContext ctx = TodoRequestContext.create("setCopiedToMeRead", request)
.disableUpdateCard()
.addLogContent("state", PendingMessageStateEnum.READ) .addLogContent("state", PendingMessageStateEnum.READ)
.addLogContent("isSetAllRead", StringUtils.isBlank(identityCode)); .addLogContent("isSetAllRead", StringUtils.isBlank(identityCode));
StateAdvanceResult advanceResult = advanceState(ctx, copiedAdvanceBuilder() StateAdvanceResult advanceResult = advanceState(ctx, copiedAdvanceBuilder()
@ -731,7 +691,7 @@ public class TodoManager {
broadcastHandler = () -> { broadcastHandler = () -> {
if (!updatedTodoIds.isEmpty()) { if (!updatedTodoIds.isEmpty()) {
List<Todo> updatedTodos = todoDao.listByIds(updatedTodoIds); List<Todo> updatedTodos = todoDao.listByIds(updatedTodoIds);
todoBroadcaster.fireTodoUpdates(ctx.getName(), updatedTodos); todoBroadcaster.fireTodoUpdates(ctx.getName(), updatedTodos, ctx.isUpdateCard());
} }
}; };
if (!ctx.isDelayBroadcast()) if (!ctx.isDelayBroadcast())

View File

@ -18,6 +18,7 @@ public class TodoRequestContext {
private final String requestNo; private final String requestNo;
private final Map<String, Object> logContents = new LinkedHashMap<>(); private final Map<String, Object> logContents = new LinkedHashMap<>();
private boolean delayBroadcast = false; private boolean delayBroadcast = false;
private boolean updateCard = true;
private TodoRequestContext(String name, String requestNo, Object request) { private TodoRequestContext(String name, String requestNo, Object request) {
this.name = name; this.name = name;
@ -53,6 +54,11 @@ public class TodoRequestContext {
return this; return this;
} }
public TodoRequestContext disableUpdateCard() {
this.updateCard = false;
return this;
}
public TodoRequestContext addLogContent(String name, Object value) { public TodoRequestContext addLogContent(String name, Object value) {
if (name == null || value == null) if (name == null || value == null)
return this; return this;

View File

@ -26,11 +26,16 @@ public class TodoBroadcaster {
private final TodoPullBroadcaster todoPullBroadcaster; private final TodoPullBroadcaster todoPullBroadcaster;
private final TodoDao todoDao; private final TodoDao todoDao;
public void fireTodoUpdates(String operation, Todo todo) { public void fireTodoUpdates(String operation, Long businessId, boolean updateCard) {
fireTodoUpdates(operation, Collections.singletonList(todo)); List<Todo> todos = todoDao.getByBusinessIds(Collections.singletonList(businessId));
fireTodoUpdates(operation, todos, updateCard);
} }
public void fireTodoUpdates(String operation, List<Todo> todos) { public void fireTodoUpdates(String operation, Todo todo, boolean updateCard) {
fireTodoUpdates(operation, Collections.singletonList(todo), updateCard);
}
public void fireTodoUpdates(String operation, List<Todo> todos, boolean updateCard) {
if (CollectionUtils.isEmpty(todos)) if (CollectionUtils.isEmpty(todos))
return; return;
List<Long> todoIds = todos.stream() List<Long> todoIds = todos.stream()
@ -42,7 +47,7 @@ public class TodoBroadcaster {
log.warn("发送待办通知时, 查询不到最新的待办信息. todoIds={}", JSON.toJSONString(todoIds)); log.warn("发送待办通知时, 查询不到最新的待办信息. todoIds={}", JSON.toJSONString(todoIds));
return; return;
} }
todoMqBroadcaster.fireTodoUpdated(operation, todos); todoMqBroadcaster.fireTodoUpdated(operation, todos, updateCard);
todoPullBroadcaster.fireTodoChanged(todos); todoPullBroadcaster.fireTodoChanged(todos);
} }

View File

@ -26,16 +26,17 @@ public class TodoMqBroadcaster {
private final MqProducer mqProducer; private final MqProducer mqProducer;
private final TodoBusinessDao todoBusinessDao; private final TodoBusinessDao todoBusinessDao;
public void fireTodoUpdated(String operation, List<Todo> todos) { public void fireTodoUpdated(String operation, List<Todo> todos, boolean updateCard) {
TodoBusinesses businesses = todoBusinessDao.getBusinesses(todos); TodoBusinesses businesses = todoBusinessDao.getBusinesses(todos);
for (Todo todo : todos) for (Todo todo : todos)
fireTodoUpdated(operation, businesses, todo); fireTodoUpdated(operation, businesses, todo, updateCard);
} }
private void fireTodoUpdated(String operation, TodoBusinesses businesses, Todo todo) { private void fireTodoUpdated(String operation, TodoBusinesses businesses, Todo todo, boolean updateCard) {
TodoUpdateMessage message = new TodoUpdateMessage(); TodoUpdateMessage message = new TodoUpdateMessage();
message.setOperation(operation); message.setOperation(operation);
message.setUpdatedTodo(createTodoInfo(businesses, todo)); message.setUpdatedTodo(createTodoInfo(businesses, todo));
message.setUpdateCard(updateCard);
mqProducer.send(MqMessageRecord mqProducer.send(MqMessageRecord
.builder(MqMessageType.TODO_STATE_UPDATE, message) .builder(MqMessageType.TODO_STATE_UPDATE, message)
.messageKey(todo.getId()) .messageKey(todo.getId())

View File

@ -0,0 +1,27 @@
package cn.axzo.msg.center.mq;
/**
* @author yanglin
*/
public enum ConsumerIsolation {
TODO_SYNC_CARD_BIZ,
TODO_SYNC_CARD_FLOW,
;
private static final ThreadLocal<ConsumerIsolation> INSTANCE = new ThreadLocal<>();
public static void setIsolation(ConsumerIsolation isolation) {
INSTANCE.set(isolation);
}
public static ConsumerIsolation getIsolation() {
return INSTANCE.get();
}
public static void clearIsolation() {
INSTANCE.remove();
}
}

View File

@ -162,4 +162,50 @@ public class RocketMQConfig {
} }
} }
@Slf4j
@Component
@RocketMQMessageListener(topic = "topic_msg_center_${spring.profiles.active}",
consumerGroup = "GID_topic_todo_sync_card_biz_${spring.profiles.active}",
consumeMode = ConsumeMode.ORDERLY,
nameServer = "${rocketmq.name-server}"
)
public static class TodoSyncCardBizListener extends BaseListener implements RocketMQListener<MessageExt> {
@Autowired
private EventConsumer eventConsumer;
@Override
public void onMessage(MessageExt message) {
ConsumerIsolation.setIsolation(ConsumerIsolation.TODO_SYNC_CARD_BIZ);
try {
super.onEvent(message, eventConsumer);
} finally {
ConsumerIsolation.clearIsolation();
}
}
}
@Slf4j
@Component
@RocketMQMessageListener(topic = "topic_msg_center_${spring.profiles.active}",
consumerGroup = "GID_topic_todo_sync_card_flow_${spring.profiles.active}",
consumeMode = ConsumeMode.ORDERLY,
nameServer = "${rocketmq.name-server}"
)
public static class TodoSyncCardFlowListener extends BaseListener implements RocketMQListener<MessageExt> {
@Autowired
private EventConsumer eventConsumer;
@Override
public void onMessage(MessageExt message) {
ConsumerIsolation.setIsolation(ConsumerIsolation.TODO_SYNC_CARD_FLOW);
try {
super.onEvent(message, eventConsumer);
} finally {
ConsumerIsolation.clearIsolation();
}
}
}
} }

View File

@ -1,5 +1,6 @@
package cn.axzo.msg.center.api.mq; package cn.axzo.msg.center.api.mq;
import com.alibaba.fastjson.JSON;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -9,6 +10,7 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class TodoUpdateMessage extends MqMessage { public class TodoUpdateMessage extends MqMessage {
/** /**
* 什么操作导致这次变化 * 什么操作导致这次变化
*/ */
@ -17,4 +19,15 @@ public class TodoUpdateMessage extends MqMessage {
* 待办信息 * 待办信息
*/ */
private TodoInfo updatedTodo; private TodoInfo updatedTodo;
/**
* 是否需要更新卡片
*/
private boolean updateCard;
@Override
public String toString() {
return JSON.toJSONString(this);
}
} }

View File

@ -1,6 +1,9 @@
package cn.axzo.msg.center.service; package cn.axzo.msg.center.service;
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
import cn.axzo.msg.center.service.enums.CodeDefinition;
import cn.axzo.msg.center.service.enums.PresetButtonType; import cn.axzo.msg.center.service.enums.PresetButtonType;
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum; import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
/** /**
@ -22,6 +25,8 @@ public interface ButtonV3 {
RouterCategoryEnum getCategory(); RouterCategoryEnum getCategory();
RouterButtonSourceEnum getSource();
default boolean determineIsPendingShow() { default boolean determineIsPendingShow() {
return getPendingShow() != null && getPendingShow(); return getPendingShow() != null && getPendingShow();
} }
@ -31,6 +36,10 @@ public interface ButtonV3 {
} }
default boolean isPerformActionAvailable() { default boolean isPerformActionAvailable() {
if (getSource() == RouterButtonSourceEnum.SYSTEM) {
BizFinalStateEnum bizFinalState = CodeDefinition.findByCode(BizFinalStateEnum.class, getCode()).orElse(null);
return bizFinalState != null && bizFinalState.isEnableActionPerformed();
}
return determineIsPendingShow() || getCategory() == RouterCategoryEnum.PRESET_BUTTON; return determineIsPendingShow() || getCategory() == RouterCategoryEnum.PRESET_BUTTON;
} }

View File

@ -27,7 +27,7 @@ public class PeerPerson {
return person; return person;
} }
public static PeerPerson newPeerPerson(Long personId, Long ouId, Long workspaceId) { public static PeerPerson create(Long personId, Long ouId, Long workspaceId) {
PeerPerson person = new PeerPerson(); PeerPerson person = new PeerPerson();
person.setPersonId(personId); person.setPersonId(personId);
person.setOuId(ouId); person.setOuId(ouId);

View File

@ -13,10 +13,15 @@ import lombok.Getter;
*/ */
@Getter @Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum BizCategoryEnum { public enum BizCategoryEnum implements CodeDefinition<String> {
FLOW("流程"), OTHER("其它"), FLOW("流程"), OTHER("其它"),
; ;
private final String desc; private final String desc;
@Override
public String getCode() {
return name();
}
} }

View File

@ -5,12 +5,10 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* @description
* 业务终态的状态枚举包含审批流的相关状态
*
* @author cold_blade * @author cold_blade
* @date 2023/11/7
* @version 1.0 * @version 1.0
* @description 业务终态的状态枚举包含审批流的相关状态
* @date 2023/11/7
*/ */
@Getter @Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE)
@ -19,24 +17,26 @@ public enum BizFinalStateEnum implements CodeDefinition<String> {
/** /**
* 已处理 * 已处理
*/ */
COMPLETED("https://static.axzo.cn/fe-static/uni-icon/public/seal-1%23_%241699341908382.png"), COMPLETED("", false, "https://static.axzo.cn/fe-static/uni-icon/public/seal-1%23_%241699341908382.png"),
/** /**
* 已撤销 * 已撤销
*/ */
RETRACT("https://static.axzo.cn/fe-static/uni-icon/native/%E5%8E%9F%E7%A8%BF%23_%241711338477975.png"), RETRACT("BPMN_REVOCATION", true, "https://static.axzo.cn/fe-static/uni-icon/native/%E5%8E%9F%E7%A8%BF%23_%241711338477975.png"),
/** /**
* 已通过 * 已通过
*/ */
PASSED("https://static.axzo.cn/fe-static/uni-icon/public/seal-4%23_%241699341908374.png"), PASSED("BPMN_APPROVE", true, "https://static.axzo.cn/fe-static/uni-icon/public/seal-4%23_%241699341908374.png"),
/** /**
* 已拒绝 * 已拒绝
*/ */
REJECTED("https://static.axzo.cn/fe-static/uni-icon/public/seal-2%23_%241699341908381.png"), REJECTED("BPMN_REJECT", true, "https://static.axzo.cn/fe-static/uni-icon/public/seal-2%23_%241699341908381.png"),
/** /**
* 已终止 * 已终止
*/ */
ABORTED("https://axzo-public.oss-cn-chengdu.aliyuncs.com/%E5%8D%B0%E7%AB%A0-%E8%AF%A6%E6%83%85end.png"); ABORTED("", false, "https://axzo-public.oss-cn-chengdu.aliyuncs.com/%E5%8D%B0%E7%AB%A0-%E8%AF%A6%E6%83%85end.png");
private final String buttonCode;
private final boolean enableActionPerformed;
private final String icon; private final String icon;
@Override @Override

View File

@ -19,11 +19,9 @@ import java.util.Objects;
public enum PendingMessageStateEnum implements CodeDefinition<String> { public enum PendingMessageStateEnum implements CodeDefinition<String> {
CREATED(0, "创建"), CREATED(0, "创建"),
UNSENT(1, "未发送"),
HAS_BEEN_SENT(2, "代办"), HAS_BEEN_SENT(2, "代办"),
COMPLETED(5, "已办"), COMPLETED(5, "已办"),
RETRACT(6, "已撤回"), RETRACT(6, "已撤回"),
DELETED(7, "已删除"),
READ(8, "已读"), READ(8, "已读"),
PROCESSING(9, "处理中") PROCESSING(9, "处理中")
; ;

View File

@ -24,16 +24,18 @@ public class CardUpdateStateRequest extends CardUpdateRequest {
private Boolean cardCompleted; private Boolean cardCompleted;
public void validate() { public void validate() {
if (!determineIsCardCompleted() && bizState == null) if (!isValid()) throw new ServiceException("cardCompleted 和 bizState 不能同时为空");
throw new ServiceException("cardCompleted 和 bizState 不能同时为空"); }
public boolean isValid() {
return determineIsCardCompleted() || bizState != null;
} }
public boolean determineIsCardCompleted() { public boolean determineIsCardCompleted() {
return cardCompleted != null && cardCompleted; return cardCompleted != null && cardCompleted;
} }
@Override @Override public String toString() {
public String toString() {
return JSON.toJSONString(this); return JSON.toJSONString(this);
} }

View File

@ -191,11 +191,15 @@ public class Todo extends BaseEntityExt<Todo> implements MessageEntity {
@Override @Override
public JSONObject bizParam() { public JSONObject bizParam() {
return bizExtParam == null ? new JSONObject() : bizExtParam; if (bizExtParam == null)
bizExtParam = new JSONObject();
return bizExtParam;
} }
@Override @Override
public JSONObject routerParam() { public JSONObject routerParam() {
return routerParams == null ? new JSONObject() : routerParams; if (routerParams == null)
routerParams = new JSONObject();
return routerParams;
} }
} }