Merge branch 'feature/REQ-3045' into dev

This commit is contained in:
yanglin 2024-10-16 18:16:46 +08:00
commit 4e07b0091e
40 changed files with 1245 additions and 280 deletions

View File

@ -153,6 +153,10 @@
<groupId>cn.axzo.im.center</groupId>
<artifactId>im-center-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.meepo</groupId>
<artifactId>meepo-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.basics</groupId>
<artifactId>basics-profiles-api</artifactId>

View File

@ -113,7 +113,11 @@ public class PendingMessageBizConfig {
@Getter
private Set<String> populateWorkspaceIdTemplateCodes = new HashSet<>();
private boolean appendRouterParamsAsQueryParams = false;
public boolean isConcatRouterParams(String templateCode) {
if (!appendRouterParamsAsQueryParams)
return false;
return dontConcatRouterParamsTemplateCodes == null || !dontConcatRouterParamsTemplateCodes.contains(templateCode);
}

View File

@ -19,6 +19,7 @@ import cn.axzo.msg.center.service.pending.request.GetPendingTodosRequest;
import cn.axzo.msg.center.service.pending.request.GetTodoRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageByBizCodeRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageCountUncompletedRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageDetailRequestV3;
import cn.axzo.msg.center.service.pending.request.PendingMessageFixedTemplatePageRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageIterateRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest;
@ -160,6 +161,11 @@ public class PendingMessageNewController implements PendingMessageClient {
return CommonResponse.success(response);
}
@Override
public CommonResponse<PendingMessageResponse> detailV3(PendingMessageDetailRequestV3 requestV3) {
return CommonResponse.success();
}
@Override
public CommonResponse<PendingMessageResponse> getLatestTodoByBiz(
String templateCode, String bizCode, String subBizCode, String todoType) {

View File

@ -3,8 +3,11 @@ package cn.axzo.msg.center.message.domain.dto;
import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@ -14,7 +17,7 @@ import java.util.List;
*/
@Setter
@Getter
public class MessageTemplateModelV3 {
public class ModelV3 {
@NotNull private MessageTemplateV3 template;
@NotNull private List<MessageTemplateGroupV3> groups;
@ -24,4 +27,13 @@ public class MessageTemplateModelV3 {
return template.getCode();
}
public MessageCategoryEnum getTemplateCategory() {
return template.getMsgCategory();
}
public boolean hasPresetButtons() {
return buttons.stream()
.anyMatch(btn -> btn.getCategory() == RouterCategoryEnum.PRESET_BUTTON);
}
}

View File

@ -45,7 +45,6 @@ import cn.axzo.msg.center.message.service.MessageGroupNodeService;
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
import cn.axzo.msg.center.message.service.PendingMessageNewService;
import cn.axzo.msg.center.message.service.impl.v3.model.OldTemplateModelPropsPopulator;
import cn.axzo.msg.center.message.service.todo.MigrateUtils;
import cn.axzo.msg.center.message.service.todo.manage.TodoExt;
import cn.axzo.msg.center.notices.common.enums.IsDeletedEnum;
@ -156,7 +155,6 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
private final PendingMessageBizConfig pendingMessageBizConfig;
private final MessageGroupNodeDao messageGroupNodeDao;
private final MessageRouterUtil messageRouterUtil;;
private final OldTemplateModelPropsPopulator oldTemplateModelPropsPopulator;
@Value("${msg.center.pending.hide-seconds:60}")
private int pendingDefaultHideSeconds;

View File

@ -0,0 +1,132 @@
package cn.axzo.msg.center.message.service.impl.v3;
import cn.axzo.basics.profiles.api.UserProfileServiceApi;
import cn.axzo.basics.profiles.dto.basic.BasicDto;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
import cn.axzo.basics.profiles.dto.basic.ProfessionTagDto;
import cn.axzo.basics.profiles.dto.basic.WorkerProfileDto;
import cn.axzo.meepo.api.BankCardApi;
import cn.axzo.meepo.api.dto.response.WorkerBankCardRes;
import cn.axzo.msg.center.common.utils.BizAssertions;
import cn.axzo.msg.center.service.pending.response.v3.model.ComponentWorkerGroup;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedKV;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import cn.axzo.msg.center.service.pending.response.v3.model.PersonInfo;
import cn.axzo.msg.center.service.pending.response.v3.model.WorkerInfo;
import cn.axzo.trade.datasecurity.core.util.DataSecurityHelper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
/**
* @author yanglin
*/
@Component
@RequiredArgsConstructor
public class ModelV3ExtPopulator {
private final UserProfileServiceApi userProfileServiceApi;
private final BankCardApi bankCardApi;
public void populate(ParsedModelV3... models) {
ArrayList<ParsedKV> personKeyValues = new ArrayList<>();
List<ComponentWorkerGroup> componentWorkerGroups = new ArrayList<>();
for (ParsedModelV3 model : models) {
personKeyValues.addAll(model.getPersonKeyValues());
componentWorkerGroups.addAll(model.getComponentWorkerGroups());
}
populatePersonKV(personKeyValues);
populateComponentWorkGroup(componentWorkerGroups);
}
private void populatePersonKV(List<ParsedKV> keyValues) {
if (CollectionUtils.isEmpty(keyValues)) return;
List<Long> personIds = keyValues.stream()
.map(ParsedKV::getValueAsLong)
.filter(Objects::nonNull)
.distinct()
.collect(toList());
Map<Long, PersonProfileDto> personId2Profile = BizAssertions.assertResponse(
userProfileServiceApi.postPersonProfiles(personIds)).stream()
.collect(toMap(BasicDto::getId, identity()));
for (ParsedKV kv : keyValues) {
Long personId = kv.getValueAsLong();
if (personId == null) continue;
PersonProfileDto profile = personId2Profile.get(personId);
if (profile == null) continue;
PersonInfo personInfo = new PersonInfo();
personInfo.setRealName(profile.getRealName());
personInfo.setAvatar(profile.getAvatarUrl());
personInfo.setMobilePhone(profile.getPhone());
personInfo.setMobilePhoneCiphertext(DataSecurityHelper.encrypt(profile.getPhone()));
kv.setPersonInfo(personInfo);
}
}
private void populateComponentWorkGroup(List<ComponentWorkerGroup> groups) {
if (CollectionUtils.isEmpty(groups)) return;
List<Long> personIds = groups.stream()
.map(ComponentWorkerGroup::getPersonId)
.distinct()
.collect(toList());
Map<Long, WorkerProfileDto> personId2WorkerProfile = BizAssertions.assertResponse(
userProfileServiceApi.postWorkerProfileList(personIds)).stream()
.collect(toMap(workerProfileDto -> workerProfileDto.getPersonProfile().getId(), identity()));
Map<Long, List<WorkerBankCardRes>> personId2BankCard = BizAssertions.assertResponse(
bankCardApi.batchGetBankByAxzoUserId(personIds)).stream()
.collect(groupingBy(WorkerBankCardRes::getPersonId));
for (ComponentWorkerGroup workerGroup : groups) {
WorkerProfileDto worker = personId2WorkerProfile.get(workerGroup.getPersonId());
if (worker == null) continue;
PersonProfileDto person = worker.getPersonProfile();
WorkerInfo workerInfo = new WorkerInfo();
workerInfo.setName(person.getRealName());
workerInfo.setIcon(person.getAvatarUrl());
workerInfo.setPhone(person.getPhone());
workerInfo.setPhoneCiphertext(DataSecurityHelper.encrypt(person.getPhone()));
workerInfo.setBirthday(person.getBirthday());
workerInfo.setNationality(person.getNationality());
workerInfo.setIdNumber(person.getIdNumber());
workerInfo.setIdNumberCiphertext(DataSecurityHelper.encrypt(person.getIdNumber()));
workerInfo.setIdentityValid(isWorkerIdentityValid(worker));
List<WorkerBankCardRes> bankCards = personId2BankCard.get(workerGroup.getPersonId());
workerInfo.setCardValid(CollectionUtils.isNotEmpty(bankCards)
&& StringUtils.isNotBlank(bankCards.get(0).getBankCardNo()));
workerInfo.setProfessionNames(worker.getProfessionTags().stream()
.map(ProfessionTagDto::getProfessionName)
.collect(joining("")));
workerGroup.getGroup().setWorkerInfo(workerInfo);
}
}
/**
* 从yoke拷贝过来的
*/
private boolean isWorkerIdentityValid(WorkerProfileDto worker) {
if (worker == null) return false;
PersonProfileDto personProfile = worker.getPersonProfile();
return !(null == personProfile
|| !StringUtils.isNotBlank(personProfile.getIdNumber())
|| !StringUtils.isNotBlank(personProfile.getRealName())
|| !StringUtils.isNotBlank(personProfile.getSex().toString())
|| !StringUtils.isNotBlank(personProfile.getNationality())
|| null == personProfile.getBirthday()
|| !StringUtils.isNotBlank(personProfile.getIdAddress())
|| !StringUtils.isNotBlank(personProfile.getIdAuthority())
|| null == personProfile.getIdStartDate()
|| null == personProfile.getIdEndDate()
|| !StringUtils.isNotBlank(personProfile.getAvatarUrl()));
}
}

View File

@ -0,0 +1,243 @@
package cn.axzo.msg.center.message.service.impl.v3;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.framework.jackson.utility.JSON;
import cn.axzo.msg.center.domain.entity.MessageEntity;
import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3;
import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
import cn.axzo.msg.center.message.domain.dto.ModelV3;
import cn.axzo.msg.center.message.service.todo.manage.TodoExt;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfigVisitor;
import cn.axzo.msg.center.service.domain.UrlConfigWalker;
import cn.axzo.msg.center.service.domain.url.AppUrl;
import cn.axzo.msg.center.service.domain.url.WebUrl;
import cn.axzo.msg.center.service.enums.GroupType;
import cn.axzo.msg.center.service.enums.KVContentType;
import cn.axzo.msg.center.service.pending.response.v3.ParsedModel3Visitor;
import cn.axzo.msg.center.service.pending.response.v3.ParsedModel3Walker;
import cn.axzo.msg.center.service.pending.response.v3.model.ComponentWorkerGroup;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedButtonV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupInfo;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedKV;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedTemplateV3;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Component;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import static cn.axzo.msg.center.common.utils.PlaceholderResolver.getDefaultResolver;
/**
* @author yanglin
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ModelV3Parser {
private static final String CUSTOMER_PERSON_ID = "customerPersonId";
private final PendingMessageBizConfig cfg;
public ParsedModelV3 parseModel(ModelV3 model,
MessageEntity entity,
JSONObject bizParam,
JSONObject routerParam) {
ParsedModelV3 parsedModel = new ParsedModelV3();
parsedModel.setTemplate(BeanMapper.copyBean(model, ParsedTemplateV3.class));
parsedModel.setGroups(copyGroups(model.getGroups()));
parsedModel.setButtons(BeanMapper.copyList(model.getButtons(), ParsedButtonV3.class));
UrlParser urlParser = new UrlParser(entity, routerParam);
ParsedModel3Walker.walkDown(parsedModel, new ParsedModel3Visitor() {
@Override
public void visitTemplateCardUrlConfig(UrlConfig urlConfig) {
urlParser.parseUrlConfig(urlConfig);
}
@Override
public void visitGroup(ParsedGroupV3 group) {
if (group.getGroupType() == GroupType.COMPONENT_WORKER) {
Long personId = bizParam.getLong(CUSTOMER_PERSON_ID);
if (personId != null && personId > 0)
parsedModel.addComponentWorkerGroup(new ComponentWorkerGroup(group, personId));
}
}
@Override
public void visitGroupKeyValue(ParsedGroupV3 group, ParsedKV kv) {
kv.setValue(getDefaultResolver().resolveByMap(kv.getValue(), bizParam));
if (kv.getContentType() == KVContentType.PERSON_ID
&& StringUtils.isNotBlank(kv.getValue())
&& NumberUtils.isDigits(kv.getValue())) {
parsedModel.addPersonKV(kv);
}
}
@Override
public void exitGroupInfo(ParsedGroupV3 group, ParsedGroupInfo groupInfo) {
groupInfo.removeEmptyValues();
}
@Override
public void visitGroupDetailUrl(ParsedGroupV3 group, UrlConfig urlConfig) {
urlParser.parseUrlConfig(urlConfig);
}
@Override
public void visitButton(ParsedButtonV3 button) {
button.setApiUrl(urlParser.parseUrl(button.getApiUrl()));
}
@Override
public void visitButtonUrlConfig(ParsedButtonV3 button, UrlConfig urlConfig) {
urlParser.parseUrlConfig(urlConfig);
}
@Override
public void exitModel(ParsedModelV3 model) {
model.removeEmptyKVGroups();
}
});
return parsedModel;
}
private List<ParsedGroupV3> copyGroups(List<MessageTemplateGroupV3> groups) {
String jsonArray = JSON.toJSONString(groups);
return JSON.parseList(jsonArray, ParsedGroupV3.class);
}
public UrlConfig parseUrlConfig(UrlConfig urlConfig,
MessageEntity entity,
JSONObject routerParam) {
String json = JSON.toJSONString(urlConfig);
UrlConfig copy = JSON.parseObject(json, UrlConfig.class);
new UrlParser(entity, routerParam).parseUrlConfig(copy);
return copy;
}
@RequiredArgsConstructor
private class UrlParser implements UrlConfigVisitor {
final MessageEntity entity;
final JSONObject routerParam;
void parseUrlConfig(UrlConfig urlConfig) {
UrlConfigWalker.walkDown(urlConfig, this);
}
@Override
public void visitPcOms(WebUrl pcOms) {
pcOms.setUrl(parseUrl(pcOms.getUrl()));
}
@Override
public void visitPcCms(WebUrl pcCms) {
pcCms.setUrl(parseUrl(pcCms.getUrl()));
}
@Override
public void visitPcGaGeneral(WebUrl pcGaGeneral) {
pcGaGeneral.setUrl(parseUrl(pcGaGeneral.getUrl()));
}
@Override
public void visitAppWorkerIos(AppUrl ios) {
ios.setUrl(parseUrl(ios.getUrl()));
}
@Override
public void visitAppWorkerAndroid(AppUrl android) {
android.setUrl(parseUrl(android.getUrl()));
}
@Override
public void visitAppManagerIos(AppUrl ios) {
ios.setUrl(parseUrl(ios.getUrl()));
}
@Override
public void visitAppManagerAndroid(AppUrl android) {
android.setUrl(parseUrl(android.getUrl()));
}
String parseUrl(String url) {
if (StringUtils.isBlank(url))
return url;
boolean populateWorkspaceId =
// @formatter:off
cfg.getPopulateWorkspaceIdTemplateCodes().contains(entity.getTemplateCode())
&& entity.getReceiverWorkspaceId() != null
&& entity.getReceiverWorkspaceId() > 0L
&& !routerParam.containsKey("workspaceId")
&& url.matches(".*\\$\\{\\s*workspaceId\\s*}.*");
// @formatter:on
if (populateWorkspaceId)
routerParam.put("workspaceId", entity.getReceiverWorkspaceId());
try {
String parsedUrl = getDefaultResolver().resolveByMap(url, routerParam);
if (cfg.isConcatRouterParams(entity.getTemplateCode()))
parsedUrl = appendRouterParam(parsedUrl, routerParam);
return parsedUrl;
} finally {
if (populateWorkspaceId)
routerParam.remove("workspaceId");
}
}
String appendRouterParam(String url, JSONObject routerParam) {
Object ctx = routerParam.remove(TodoExt.CTX);
try {
if (routerParam.isEmpty()) {
return url;
}
StringBuilder paramBuilder = new StringBuilder();
for (Map.Entry<String, Object> entry : routerParam.entrySet()) {
if (url.contains(entry.getKey() + "=")) {
continue;
}
String value = tryEncode(entry.getValue());
paramBuilder.append("&").append(entry.getKey()).append("=").append(value);
}
if (StringUtils.isBlank(paramBuilder.toString())) {
return url;
}
if (!url.contains("?")) {
// 替换掉第一个参数分隔符(&)
paramBuilder.replace(0, 1, "?");
}
return url + paramBuilder;
} finally {
if (ctx != null) {
routerParam.put(TodoExt.CTX, ctx);
}
}
}
String tryEncode(Object o) {
String value = String.valueOf(o);
try {
value = URLEncoder.encode(value, "UTF-8");
} catch (Exception e) {
log.warn("error encode pending dynamic value. value={}", value);
}
return value;
}
}
}

View File

@ -1,4 +1,4 @@
package cn.axzo.msg.center.message.service.impl.v3.model;
package cn.axzo.msg.center.message.service.impl.v3;
import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao;
import cn.axzo.msg.center.dal.MessageTemplateGroupV3Dao;
@ -6,7 +6,7 @@ import cn.axzo.msg.center.dal.MessageTemplateV3Dao;
import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateModelV3;
import cn.axzo.msg.center.message.domain.dto.ModelV3;
import cn.axzo.msg.center.service.enums.StatusEnum;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
@ -26,14 +26,13 @@ import static java.util.stream.Collectors.toList;
*/
@Service
@RequiredArgsConstructor
public class TemplateModelV3Service {
public class ModelV3Service {
private final MessageTemplateV3Dao messageTemplateV3Dao;
private final MessageTemplateGroupV3Dao messageTemplateGroupV3Dao;
private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao;
private final TemplateModelV3PropsParser propsParser;
public Optional<MessageTemplateModelV3> findEnabledByCode(String templateCode, boolean parseProps) {
public Optional<ModelV3> findEnabledByCode(String templateCode) {
MessageTemplateV3 template = messageTemplateV3Dao.lambdaQuery()
.eq(MessageTemplateV3::getCode, templateCode)
.eq(MessageTemplateV3::getIsDelete, 0)
@ -41,18 +40,18 @@ public class TemplateModelV3Service {
.one();
if (template == null)
return Optional.empty();
ModelBuilder builder = new ModelBuilder(parseProps, templateCode);
ModelBuilder builder = new ModelBuilder(templateCode);
return Optional.of(builder.build(template));
}
public List<MessageTemplateModelV3> getByCodes(List<String> templateCodes, boolean parseProps) {
public List<ModelV3> getByCodes(List<String> templateCodes) {
if (CollectionUtils.isEmpty(templateCodes))
return Collections.emptyList();
List<MessageTemplateV3> templates = messageTemplateV3Dao.lambdaQuery()
.in(MessageTemplateV3::getCode, templateCodes)
.eq(MessageTemplateV3::getIsDelete, 0)
.list();
ModelBuilder builder = new ModelBuilder(parseProps, templateCodes.toArray(new String[0]));
ModelBuilder builder = new ModelBuilder(templateCodes.toArray(new String[0]));
return templates.stream()
.map(builder::build)
.collect(toList());
@ -61,12 +60,10 @@ public class TemplateModelV3Service {
@RequiredArgsConstructor
private class ModelBuilder {
final boolean parseProps;
final Map<String, List<MessageTemplateGroupV3>> templateCode2Groups;
final Map<String, List<MessageTemplateButtonV3>> templateCode2Buttons;
ModelBuilder(boolean parseProps, String... templateCodes) {
this.parseProps = parseProps;
ModelBuilder(String... templateCodes) {
if (templateCodes.length > 0) {
templateCode2Groups = messageTemplateGroupV3Dao.lambdaQuery()
.in(MessageTemplateGroupV3::getTemplateCode, Arrays.asList(templateCodes))
@ -82,12 +79,11 @@ public class TemplateModelV3Service {
}
}
MessageTemplateModelV3 build(MessageTemplateV3 template) {
MessageTemplateModelV3 model = new MessageTemplateModelV3();
ModelV3 build(MessageTemplateV3 template) {
ModelV3 model = new ModelV3();
model.setTemplate(template);
model.setGroups(templateCode2Groups.getOrDefault(template.getCode(), Collections.emptyList()));
model.setButtons(templateCode2Buttons.getOrDefault(template.getCode(), Collections.emptyList()));
propsParser.parse(model);
return model;
}

View File

@ -1,10 +0,0 @@
package cn.axzo.msg.center.message.service.impl.v3.model;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Component
public class OldTemplateModelPropsPopulator {
}

View File

@ -1,15 +0,0 @@
package cn.axzo.msg.center.message.service.impl.v3.model;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateModelV3;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Component
class TemplateModelV3PropsParser {
void parse(MessageTemplateModelV3 model) {
}
}

View File

@ -3,7 +3,7 @@ package cn.axzo.msg.center.message.service.todo.manage;
import cn.axzo.msg.center.common.utils.BizAssertions;
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO;
import cn.axzo.msg.center.message.domain.dto.ModelV3;
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
import cn.axzo.msg.center.service.util.JSONUtils;
import com.alibaba.fastjson.JSONObject;
@ -21,7 +21,7 @@ public class TodoExt {
public static final String CTX = "ctx";
private final PendingMessagePushParam request;
private final MessageTemplateDTO template;
private final ModelV3 model;
private JSONObject bizExt;
private JSONObject routerExt;
@ -48,7 +48,7 @@ public class TodoExt {
if (title == null) {
JSONObject ext = (JSONObject)parseBizExtParams().clone();
ext.put(CTX, ImmutableMap.of("request", request));
title = PlaceholderResolver.tryResolve(template.getTitle(), ext);
title = PlaceholderResolver.tryResolve(model.getTemplate().getTitle(), ext);
}
return title;
}
@ -57,7 +57,7 @@ public class TodoExt {
if (content == null) {
JSONObject ext = (JSONObject)parseBizExtParams().clone();
ext.put(CTX, ImmutableMap.of("request", request));
content = PlaceholderResolver.tryResolve(template.getContent(), ext);
content = PlaceholderResolver.tryResolve(model.getTemplate().getContent(), ext);
}
return content;
}

View File

@ -14,9 +14,9 @@ import cn.axzo.msg.center.domain.entity.TodoBusiness;
import cn.axzo.msg.center.domain.entity.TodoHandoverMapping;
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO;
import cn.axzo.msg.center.message.domain.dto.ModelV3;
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service;
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.event.HandoverEvent;
@ -88,7 +88,7 @@ public class TodoManager {
private final TodoRecordBuilder todoRecordBuilder;
private final TodoLogger todoLogger;
private final TodoMqBroadcaster todoMqBroadcaster;
private final MessageTemplateNewService messageTemplateNewService;
private final ModelV3Service modelV3Service;
private final MqProducer mqProducer;
private final ErrorAssembler errorAssembler;
private final PendingMessageBizConfig cfg;
@ -121,8 +121,7 @@ public class TodoManager {
*/
private List<PushPendingMessageDTO> sendImpl(TodoRequestContext ctx, PendingMessagePushParam request) {
// 可能会存在重新查询模版的情况, 成本不高
MessageTemplateDTO template = messageTemplateNewService
.queryEnableTemplateByCode(request.getTemplateCode())
ModelV3 model = modelV3Service.findEnabledByCode(request.getTemplateCode())
.orElseThrow(() -> new ServiceException(
String.format("Can't find template. templateCode=%s", request.getTemplateCode())));
BizAssertions.assertNotEmpty(request.getExecutor(), "接受者不能为空");
@ -132,7 +131,7 @@ public class TodoManager {
// 1. 让他们改造, 传bizCode
// 2. 待办自动生成bizCode
// 3. 如果是系统生成的待办, 那么就不会有问题. 目前生成上有2个模版(进场出场)都是系统生成的
boolean genBizCode = cfg.getGenBizCodeTemplates().contains(template.getCode());
boolean genBizCode = cfg.getGenBizCodeTemplates().contains(model.getTemplateCode());
if (genBizCode)
request.setBizCode(UUIDUtil.uuidString());
else if (StringUtils.isBlank(request.getBizCode()))
@ -143,7 +142,7 @@ public class TodoManager {
.findByBiz(request.getTemplateCode(), request.getBizCode(), true)
.orElse(null);
boolean businessCreated = false;
TodoExt ext = new TodoExt(request, template);
TodoExt ext = new TodoExt(request, model);
if (business == null) {
business = todoRecordBuilder.buildBusiness(request, ext);
business.getRecordExt().setGenBizCode(genBizCode);
@ -153,8 +152,8 @@ public class TodoManager {
//批量默认为false
YesOrNo supportBatchProcess = request.getSupportBatchProcess() == null ? YesOrNo.NO : request.getSupportBatchProcess();
//业务待办设置是否批量处理
if (template.getMsgCategory() == MessageCategoryEnum.BIZ_PENDING_MESSAGE
&& template.hasPresetButtons())
if (model.getTemplateCategory() == MessageCategoryEnum.BIZ_PENDING_MESSAGE
&& model.hasPresetButtons())
supportBatchProcess = YesOrNo.YES;
request.setSupportBatchProcess(supportBatchProcess);
List<Todo> todos = todoRecordBuilder.buildTodos(
@ -168,8 +167,8 @@ public class TodoManager {
todoBroadcaster.fireTodoUpdates("send", todos);
// 记录日志
// @formatter:off
ctx.addLogContent("templateTitle", template.getTitle())
.addLogContent("templateContent", template.getContent())
ctx.addLogContent("templateTitle", model.getTemplate().getTitle())
.addLogContent("templateContent", model.getTemplate().getContent())
.addLogContent("title", ext.parseTitle())
.addLogContent("content", ext.parseContent())
.addLogContent("bizExtParams", ext.parseBizExtParams())
@ -180,7 +179,7 @@ public class TodoManager {
if (businessCreated)
todoLogger.logBusinessUpdated(ctx, business);
todoLogger.logTodosUpdated(ctx, todos);
applicationContext.publishEvent(new NewTodoEvent(this, template, todos));
applicationContext.publishEvent(new NewTodoEvent(this, model, todos));
return todos.stream()
.map(todo -> new PushPendingMessageDTO(
todo.getId(), todo.getIdentityCode(),

View File

@ -1,7 +1,7 @@
package cn.axzo.msg.center.message.service.todo.manage.event;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO;
import cn.axzo.msg.center.message.domain.dto.ModelV3;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@ -14,19 +14,19 @@ import java.util.List;
*/
@Getter
public class NewTodoEvent extends ApplicationEvent {
private final MessageTemplateDTO template;
private final ModelV3 model;
private final List<Todo> todos;
public NewTodoEvent(Object source, MessageTemplateDTO template, List<Todo> todos) {
public NewTodoEvent(Object source, ModelV3 model, List<Todo> todos) {
super(source);
this.template = template;
this.model = model;
this.todos = todos;
}
@Override
public String toString() {
HashMap<String, Object> fields = new HashMap<>();
fields.put("template", template);
fields.put("model", model);
fields.put("todos", todos);
return JSON.toJSONString(fields);
}

View File

@ -4,15 +4,18 @@ import cn.axzo.msg.center.dal.TodoBusinessDao;
import cn.axzo.msg.center.dal.TodoBusinesses;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.domain.entity.TodoBusiness;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteDetailDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouterConfigDTO;
import cn.axzo.msg.center.message.domain.dto.ModelV3;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Parser;
import cn.axzo.msg.center.message.service.todo.manage.TodoExt;
import cn.axzo.msg.center.message.service.youmeng.YoumengPush;
import cn.axzo.msg.center.message.service.youmeng.YoumengPush.PushNavigation;
import cn.axzo.msg.center.message.service.youmeng.YoumengTemplateClient;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import cn.axzo.msg.center.service.domain.CardUrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfigVisitor;
import cn.axzo.msg.center.service.domain.UrlConfigWalker;
import cn.axzo.msg.center.service.domain.url.AppUrl;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -24,8 +27,9 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author yanglin
@ -36,53 +40,72 @@ import java.util.Map;
class TodoPushSender implements ApplicationListener<NewTodoEvent> {
private final YoumengTemplateClient youmengTemplateClient;
private final MessageRouterUtil messageRouterUtil;
private final TodoBusinessDao todoBusinessDao;
private final ModelV3Parser modelV3Parser;
@Override
public void onApplicationEvent(@NotNull NewTodoEvent event) {
log.info("Prepare sending todo push. event={}", event);
ArrayList<YoumengPush> pushes = new ArrayList<>();
for (Todo todo : event.getTodos()) {
Set<PushNavigation> navigations = determineNavigations(event.getModel(), todo);
if (CollectionUtils.isEmpty(navigations))
continue;
YoumengPush push = new YoumengPush();
push.setTitle(todo.getTitle());
push.setContent(todo.getContent());
push.setReceiverPersonId(todo.getExecutorPersonId());
push.setReceiverOuId(todo.getOuId());
push.setNavigations(determineNavigations(event.getTemplate(), todo));
push.setNavigations(navigations);
pushes.add(push);
}
youmengTemplateClient.asyncSend(event.getTemplate().getId(), pushes);
if (CollectionUtils.isNotEmpty(pushes))
youmengTemplateClient.asyncSend(event.getModel().getTemplate().getId(), pushes);
}
private List<PushNavigation> determineNavigations(MessageTemplateDTO template, Todo todo) {
if (template.getMsgTemplateRouter() == null)
return Collections.emptyList();
MessageRouteDetailDTO detail = template.getMsgTemplateRouter().getRouteDetail();
if (detail == null)
return Collections.emptyList();
List<MessageRouterConfigDTO> routerConfigs = detail.getRouterConfigs();
if (CollectionUtils.isEmpty(routerConfigs))
return Collections.emptyList();
private Set<PushNavigation> determineNavigations(ModelV3 model, Todo todo) {
CardUrlConfig cardUrlConfig = model.getTemplate().getCardUrlConfig();
if (cardUrlConfig == null) return Collections.emptySet();
UrlConfig urlConfig = cardUrlConfig.getUrlConfig();
if (urlConfig == null)
return Collections.emptySet();
JSONObject routerParam = todo.getRouterParams();
if (routerParam == null) {
if (routerParam == null)
routerParam = new JSONObject();
}
TodoBusinesses businesses = todoBusinessDao.getBusinesses(todo);
TodoBusiness business = businesses.findBusiness(todo).orElse(null);
Map<String, Object> ctx = new HashMap<>();
ctx.put("business", business);
ctx.put("todo", todo);
routerParam.put(TodoExt.CTX, ctx);
MessageTemplateRouterDTO router = messageRouterUtil.parseAndConcatRouteUrl(
todo, template, template.getMsgTemplateRouter(), routerParam);
if (router == null)
return Collections.emptyList();
ArrayList<PushNavigation> navigations = new ArrayList<>();
for (MessageRouterConfigDTO routerCfg : router.getRouteDetail().getRouterConfigs()) {
String url = template.isCardJumpToBiz() ? routerCfg.getUrl() : "";
navigations.add(new PushNavigation(routerCfg.getTerminalType(), url));
}
Set<PushNavigation> navigations = new HashSet<>();
UrlConfig parsedUrlConfig = modelV3Parser.parseUrlConfig(urlConfig, todo, routerParam);
UrlConfigWalker.walkDown(parsedUrlConfig, new UrlConfigVisitor() {
@Override
public void visitAppManagerAndroid(AppUrl android) {
if (android.hasUrl())
navigations.add(new PushNavigation(TerminalTypeEnum.ANDROID, android.getUrl()));
}
@Override
public void visitAppManagerIos(AppUrl ios) {
if (ios.hasUrl())
navigations.add(new PushNavigation(TerminalTypeEnum.IOS, ios.getUrl()));
}
@Override
public void visitAppWorkerAndroid(AppUrl android) {
if (android.hasUrl())
navigations.add(new PushNavigation(TerminalTypeEnum.ANDROID, android.getUrl()));
}
@Override
public void visitAppWorkerIos(AppUrl ios) {
if (ios.hasUrl())
navigations.add(new PushNavigation(TerminalTypeEnum.IOS, ios.getUrl()));
}
});
return navigations;
}
}

View File

@ -3,9 +3,12 @@ package cn.axzo.msg.center.message.service.youmeng;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* @author yanglin
@ -17,18 +20,31 @@ public class YoumengPush {
private String content;
private Long receiverPersonId;
private Long receiverOuId;
private List<PushNavigation> navigations;
private Set<PushNavigation> navigations;
Long determineReceiverOuId() {
return receiverOuId == null ? 0L : receiverOuId;
}
@Data
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class PushNavigation {
private TerminalTypeEnum platform;
private String url;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PushNavigation)) return false;
PushNavigation that = (PushNavigation) o;
return platform == that.platform && Objects.equals(url, that.url);
}
@Override
public int hashCode() {
return Objects.hash(platform, url);
}
}
}

View File

@ -2,6 +2,7 @@ package cn.axzo.msg.center.service.domain;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
@ -22,4 +23,12 @@ public class GroupConfig {
*/
private DetailConfig detail;
public void removeEmptyValues() {
if (keyValues == null) return;
keyValues.removeIf(kv -> {
String value = kv.getValue();
return StringUtils.isBlank(value) || "null".equalsIgnoreCase(value);
});
}
}

View File

@ -1,18 +1,13 @@
package cn.axzo.msg.center.service.domain;
import cn.axzo.msg.center.service.domain.parse.TerminalUrl;
import cn.axzo.msg.center.service.domain.parse.TerminalUrlParser;
import cn.axzo.msg.center.service.domain.url.AppUrl;
import cn.axzo.msg.center.service.domain.url.WebUrl;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.WebPageOpenStrategy;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* <a href="https://docs.dingtalk.com/i/nodes/14lgGw3P8v9Yk4yaF0aAo9NbJ5daZ90D">REQ-3045</a>
*
@ -47,10 +42,6 @@ public class UrlConfig {
*/
private MobileUrlConfig appManager;
public List<TerminalUrl> parse(AppTerminalTypeEnum appType) {
return new TerminalUrlParser(this, appType).parse();
}
@JsonIgnore @JSONField(serialize = false)
public WebUrl getOrCreatePcOms() {
if (pcOms == null)

View File

@ -0,0 +1,31 @@
package cn.axzo.msg.center.service.domain;
import cn.axzo.msg.center.service.domain.url.AppUrl;
import cn.axzo.msg.center.service.domain.url.WebUrl;
/**
* @author yanglin
*/
public interface UrlConfigVisitor {
default void visitUrlConfig(UrlConfig urlConfig) {};
default void visitPcOms(WebUrl pcOms) {};
default void visitPcCms(WebUrl pcCms) {};
default void visitPcGaGeneral(WebUrl pcGaGeneral) {};
default void visitAppWorker(MobileUrlConfig appWorker) {};
default void visitAppWorkerIos(AppUrl ios) {};
default void visitAppWorkerAndroid(AppUrl android) {};
default void visitAppManager(MobileUrlConfig appWorker) {};
default void visitAppManagerIos(AppUrl ios) {};
default void visitAppManagerAndroid(AppUrl android) {};
}

View File

@ -0,0 +1,51 @@
package cn.axzo.msg.center.service.domain;
/**
* @author yanglin
*/
public class UrlConfigWalker {
public static void walkDown(UrlConfig urlConfig, UrlConfigVisitor visitor) {
if (urlConfig == null) return;
visitor.visitUrlConfig(urlConfig);
visitPcOms(urlConfig, visitor);
visitPcCms(urlConfig, visitor);
visitPcGaGeneral(urlConfig, visitor);
visitAppWorker(urlConfig, visitor);
visitAppManager(urlConfig, visitor);
}
private static void visitPcOms(UrlConfig urlConfig, UrlConfigVisitor visitor) {
if (urlConfig.getPcOms() != null)
visitor.visitPcOms(urlConfig.getPcOms());
}
private static void visitPcCms(UrlConfig urlConfig, UrlConfigVisitor visitor) {
if (urlConfig.getPcCms() != null)
visitor.visitPcCms(urlConfig.getPcCms());
}
private static void visitPcGaGeneral(UrlConfig urlConfig, UrlConfigVisitor visitor) {
if (urlConfig.getPcGaGeneral() != null)
visitor.visitPcGaGeneral(urlConfig.getPcGaGeneral());
}
private static void visitAppWorker(UrlConfig urlConfig, UrlConfigVisitor visitor) {
if (urlConfig.getAppWorker() == null) return;
visitor.visitAppWorker(urlConfig.getAppWorker());
if (urlConfig.getAppWorker().getIos() != null)
visitor.visitAppWorkerIos(urlConfig.getAppWorker().getIos());
if (urlConfig.getAppWorker().getAndroid() != null)
visitor.visitAppWorkerAndroid(urlConfig.getAppWorker().getAndroid());
}
private static void visitAppManager(UrlConfig urlConfig, UrlConfigVisitor visitor) {
if (urlConfig.getAppManager() == null) return;
visitor.visitAppManager(urlConfig.getAppManager());
if (urlConfig.getAppManager().getIos() != null)
visitor.visitAppManagerIos(urlConfig.getAppManager().getIos());
if (urlConfig.getAppManager().getAndroid() != null)
visitor.visitAppManagerAndroid(urlConfig.getAppManager().getAndroid());
}
}

View File

@ -1,78 +0,0 @@
package cn.axzo.msg.center.service.domain.parse;
import cn.axzo.msg.center.service.domain.MobileUrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.domain.url.WebUrl;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import lombok.RequiredArgsConstructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.B_ENTERPRISE_APP;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.CMS_WEB_PC;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.C_WORKER_APP;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.OMS_WEB_PC;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.PC_GA_GENERAL;
/**
* @author yanglin
*/
@RequiredArgsConstructor
public class TerminalUrlParser {
private final UrlConfig config;
private final AppTerminalTypeEnum requestType;
/**
* 根据请求客户端真实的终端类型来选择对应的URL
*/
public List<TerminalUrl> parse() {
ArrayList<TerminalUrl> urls = new ArrayList<>();
// !! 只会命中其一
// PC(CMS)
selectWeb(CMS_WEB_PC, config.getPcCms()).ifPresent(urls::add);
// PC(OMS)
selectWeb(OMS_WEB_PC, config.getPcOms()).ifPresent(urls::add);
// PC(政务系统)
selectWeb(PC_GA_GENERAL, config.getPcGaGeneral()).ifPresent(urls::add);
// !! 只会命中其一
// APP工人端
urls.addAll(selectApp(C_WORKER_APP, config.getAppWorker()));
// APP管理端
urls.addAll(selectApp(B_ENTERPRISE_APP, config.getAppManager()));
return urls;
}
private Optional<TerminalUrl> selectWeb(
AppTerminalTypeEnum selectType, WebUrl webUrl) {
if (requestType != selectType)
return Optional.empty();
if (webUrl == null)
return Optional.empty();
return Optional.of(new TerminalUrl(TerminalTypeEnum.WEB, webUrl.getUrl()));
}
private List<TerminalUrl> selectApp(
AppTerminalTypeEnum selectType, MobileUrlConfig mobileUrl) {
if (requestType != selectType)
return Collections.emptyList();
if (mobileUrl == null)
return Collections.emptyList();
ArrayList<TerminalUrl> urls = new ArrayList<>();
if (mobileUrl.getIos() != null)
urls.add(new TerminalUrl(TerminalTypeEnum.IOS, mobileUrl.getIos().getUrl()));
if (mobileUrl.getAndroid() != null)
urls.add(new TerminalUrl(TerminalTypeEnum.ANDROID, mobileUrl.getAndroid().getUrl()));
return urls;
}
}

View File

@ -10,6 +10,7 @@ import cn.axzo.msg.center.service.pending.request.GetPendingTodosRequest;
import cn.axzo.msg.center.service.pending.request.GetTodoRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageByBizCodeRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageCountUncompletedRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageDetailRequestV3;
import cn.axzo.msg.center.service.pending.request.PendingMessageFixedTemplatePageRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessageIterateRequest;
import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest;
@ -161,12 +162,18 @@ public interface PendingMessageClient {
* @param terminalType APP终端类型
* @return 代办详情
*/
@Deprecated
@PostMapping(value = "/pending-message/record/detail", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<PendingMessageResponse> detail(@RequestParam("msgIdentityCode") String msgIdentityCode,
@RequestParam("terminalType") TerminalTypeEnum terminalType,
@RequestParam(value = "queryType", required = false)
TodoQueryType queryType);
@Deprecated
@PostMapping(value = "/pending-message/record/detailV3", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<PendingMessageResponse> detailV3(
@RequestBody @Valid PendingMessageDetailRequestV3 requestV3);
/**
* 根据bizCode查询待办详情
*

View File

@ -1,5 +1,6 @@
package cn.axzo.msg.center.service.pending.request;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import lombok.Getter;
import lombok.Setter;
@ -36,6 +37,8 @@ public class GetPendingTodosRequest {
private TerminalTypeEnum terminalType;
private AppTerminalTypeEnum appTerminalType;
public int determineLimit() {
if (limit <= 0)
return 10;

View File

@ -0,0 +1,19 @@
package cn.axzo.msg.center.service.pending.request;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.service.enums.TodoQueryType;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class PendingMessageDetailRequestV3 {
private String msgIdentityCode;
private TerminalTypeEnum terminalType;
private AppTerminalTypeEnum appTerminalType;
private TodoQueryType queryType;
}

View File

@ -1,5 +1,6 @@
package cn.axzo.msg.center.service.pending.request;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
@ -34,6 +35,7 @@ public class PendingMessageQueryRequest implements Serializable {
* WECHAT_MINI_PROGRAM: 微信小程序页面
*/
private TerminalTypeEnum terminalType;
private AppTerminalTypeEnum appTerminalType;
/**
* 代办消息状态
* UNSENT: 未发送

View File

@ -2,6 +2,7 @@ package cn.axzo.msg.center.service.pending.response;
import cn.axzo.msg.center.api.custombutton.ProposedButtonFilter;
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
import cn.axzo.msg.center.service.domain.CardUrlConfig;
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
import cn.axzo.msg.center.service.dto.DetailRouterDTO;
import cn.axzo.msg.center.service.dto.IdentityDTO;
@ -9,12 +10,16 @@ import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
import cn.axzo.msg.center.service.enums.CardUrlOpenStrategy;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.service.enums.TodoQueryType;
import cn.axzo.msg.center.service.enums.TodoType;
import cn.axzo.msg.center.service.pending.response.v3.TodoModelV3;
import cn.axzo.msg.center.service.pending.response.v3.ModelV2PropsPopulator;
import cn.axzo.msg.center.service.pending.response.v3.ParsedModel3Walker;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import cn.axzo.msg.center.service.template.response.MessageDetailStyle;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@ -25,15 +30,15 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @description
* 代办消息记录页面展示数模型
* @author cold_blade
* @date 2023/9/23
* @version 1.0
* @description 代办消息记录页面展示数模型
* @date 2023/9/23
*/
@Setter
@Getter
@ -63,6 +68,7 @@ public class PendingMessageResponse implements Serializable, TodoButtonProvider
/**
* 卡片信息
*/
@Deprecated
private List<MessageCardContentItemDTO> cardItems;
/**
* 代办发起者自然人id
@ -177,10 +183,12 @@ public class PendingMessageResponse implements Serializable, TodoButtonProvider
/**
* 业务详情路由
*/
@Deprecated
private DetailRouterDTO detailRouter;
/**
* 按钮路由
*/
@Deprecated
private List<ButtonRouterDTO> buttonRouters;
/**
* 业务终态的印章图片地址
@ -221,10 +229,10 @@ public class PendingMessageResponse implements Serializable, TodoButtonProvider
/**
* 查询类型
* HAS_BEEN_SENT: 待处理
* COMPLETED: 已处理
* SEND_BY_ME: 我发起
* COPIED_TO_ME: 抄送我
* HAS_BEEN_SENT: 待处理
* COMPLETED: 已处理
* SEND_BY_ME: 我发起
* COPIED_TO_ME: 抄送我
*/
private TodoQueryType queryType;
@ -249,7 +257,26 @@ public class PendingMessageResponse implements Serializable, TodoButtonProvider
/**
* 基于分组的待办信息
*/
private TodoModelV3 modelV3;
private ParsedModelV3 modelV3;
/**
* 卡片跳转方式. NONE: 无跳转, OPEN_TODO_DETAIL: 打开待办详情, OPEN_CUSTOM_PAGE: 打开指定页面
*/
private CardUrlOpenStrategy cardUrlOpenStrategy;
/**
* 卡片跳转配置. 在links的基础上再包一层, 避免以后卡片增加自己的配置
*/
private CardUrlConfig cardUrlConfig;
public void populateV2Props(TerminalTypeEnum terminalTypeInRequest,
AppTerminalTypeEnum appTypeInRequest) {
if (modelV3 == null) return;
cardItems = new ArrayList<>();
buttonRouters = new ArrayList<>();
ParsedModel3Walker.walkDown(modelV3, new ModelV2PropsPopulator(
this, terminalTypeInRequest, appTypeInRequest));
}
public void adjustProposedButtons(boolean forPromoter) {
ProposedButtonFilter.adjustProposedButtons(this, forPromoter);

View File

@ -0,0 +1,118 @@
package cn.axzo.msg.center.service.pending.response.v3;
import cn.axzo.msg.center.service.domain.MobileUrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.domain.parse.TerminalUrl;
import cn.axzo.msg.center.service.domain.url.WebUrl;
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedButtonV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedKV;
import lombok.RequiredArgsConstructor;
import java.util.Optional;
import java.util.function.Supplier;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.B_ENTERPRISE_APP;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.CMS_WEB_PC;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.C_WORKER_APP;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.OMS_WEB_PC;
import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.PC_GA_GENERAL;
/**
* @author yanglin
*/
@RequiredArgsConstructor
public class ModelV2PropsPopulator implements ParsedModel3Visitor {
private final PendingMessageResponse response;
private final TerminalTypeEnum terminalTypeInRequest;
private final AppTerminalTypeEnum appTypeInRequest;
@Override
public void visitGroupKeyValue(ParsedGroupV3 group, ParsedKV kv) {
MessageCardContentItemDTO cardItem = new MessageCardContentItemDTO();
cardItem.setLabel(kv.getKey());
cardItem.setValue(kv.getValue());
response.getCardItems().add(cardItem);
}
@Override
public void visitButton(ParsedButtonV3 buttonV3) {
Supplier<ButtonRouterDTO> factory = () -> {
ButtonRouterDTO buttonV2 = new ButtonRouterDTO();
buttonV2.setDesc("from model v3");
buttonV2.setCategory(buttonV3.getCategory());
buttonV2.setPresetButtonType(buttonV3.getPresetBtnType());
buttonV2.setStyle(buttonV3.parseStyle());
buttonV2.setExecutorShow(buttonV3.getExecutorShow());
buttonV2.setPendingShow(buttonV3.getPendingShow());
buttonV2.setKey(buttonV3.getCode());
buttonV2.setSource(buttonV3.getSource());
response.getButtonRouters().add(buttonV2);
return buttonV2;
};
if (buttonV3.getCategory() != RouterCategoryEnum.JUMP) {
ButtonRouterDTO buttonV2 = factory.get();
buttonV2.setUrl(buttonV3.getApiUrl());
return;
}
parseTerminalUrl(buttonV3.getUrlConfig()).ifPresent(terminalUrl -> {
ButtonRouterDTO buttonV2 = factory.get();
buttonV2.setUrl(terminalUrl.getUrl());
buttonV2.setTerminalType(terminalUrl.getTerminalType());
});
}
/**
* 根据请求客户端真实的终端类型来选择对应的URL
*/
public Optional<TerminalUrl> parseTerminalUrl(UrlConfig config) {
if (appTypeInRequest == null)
return Optional.empty();
if (config == null) return Optional.empty();
// PC(CMS)
TerminalUrl pcCms = selectWeb(CMS_WEB_PC, config.getPcCms());
if (pcCms != null) return Optional.of(pcCms);
// PC(OMS)
TerminalUrl pcOms = selectWeb(OMS_WEB_PC, config.getPcOms());
if (pcOms != null) return Optional.of(pcOms);
// PC(政务系统)
TerminalUrl pcGaGeneral = selectWeb(PC_GA_GENERAL, config.getPcGaGeneral());
if (pcGaGeneral != null) return Optional.of(pcGaGeneral);
// APP工人端
TerminalUrl appWorker = selectApp(C_WORKER_APP, config.getAppWorker());
if (appWorker != null) return Optional.of(appWorker);
// APP管理端
TerminalUrl appManager = selectApp(B_ENTERPRISE_APP, config.getAppManager());
return Optional.ofNullable(appManager);
}
private TerminalUrl selectWeb(
AppTerminalTypeEnum selectAppType, WebUrl webUrl) {
if (appTypeInRequest != selectAppType)
return null;
if (webUrl == null)
return null;
return new TerminalUrl(TerminalTypeEnum.WEB, webUrl.getUrl());
}
private TerminalUrl selectApp(
AppTerminalTypeEnum selectAppType, MobileUrlConfig mobileUrl) {
if (appTypeInRequest != selectAppType)
return null;
if (mobileUrl == null)
return null;
if (mobileUrl.getIos() != null && terminalTypeInRequest == TerminalTypeEnum.IOS)
return new TerminalUrl(TerminalTypeEnum.IOS, mobileUrl.getIos().getUrl());
if (mobileUrl.getAndroid() != null && terminalTypeInRequest == TerminalTypeEnum.ANDROID)
return new TerminalUrl(TerminalTypeEnum.ANDROID, mobileUrl.getAndroid().getUrl());
return null;
}
}

View File

@ -0,0 +1,57 @@
package cn.axzo.msg.center.service.pending.response.v3;
import cn.axzo.msg.center.service.domain.DetailConfig;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedButtonV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupInfo;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedKV;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedTemplateV3;
/**
* @author yanglin
*/
public interface ParsedModel3Visitor {
default void visitModel(ParsedModelV3 model) {}
default void exitModel(ParsedModelV3 model) {}
default void visitTemplate(ParsedTemplateV3 template) {}
default void exitTemplate(ParsedTemplateV3 template) {}
default void visitTemplateCardUrlConfig(UrlConfig urlConfig) {}
default void exitTemplateCardUrlConfig(UrlConfig urlConfig) {}
default void visitGroup(ParsedGroupV3 group) {}
default void exitGroup(ParsedGroupV3 group) {}
default void visitGroupInfo(ParsedGroupV3 group, ParsedGroupInfo groupInfo) {}
default void exitGroupInfo(ParsedGroupV3 group, ParsedGroupInfo groupInfo) {}
default void visitGroupKeyValue(ParsedGroupV3 group, ParsedKV kv) {}
default void exitGroupKeyValue(ParsedGroupV3 group, ParsedKV kv) {}
default void visitGroupDetail(ParsedGroupV3 group, DetailConfig detailConfig) {}
default void exitGroupDetail(ParsedGroupV3 group, DetailConfig detailConfig) {}
default void visitGroupDetailUrl(ParsedGroupV3 group, UrlConfig urlConfig) {}
default void exitGroupDetailUrl(ParsedGroupV3 group, UrlConfig urlConfig) {}
default void visitButton(ParsedButtonV3 button) {}
default void exitButton(ParsedButtonV3 button) {}
default void visitButtonUrlConfig(ParsedButtonV3 button, UrlConfig urlConfig) {}
default void exitButtonUrlConfig(ParsedButtonV3 button, UrlConfig urlConfig) {}
}

View File

@ -0,0 +1,83 @@
package cn.axzo.msg.center.service.pending.response.v3;
import cn.axzo.msg.center.service.domain.CardUrlConfig;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedButtonV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupInfo;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedKV;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedTemplateV3;
/**
* @author yanglin
*/
public class ParsedModel3Walker {
public static void walkDown(ParsedModelV3 model, ParsedModel3Visitor visitor) {
if (model == null) return;
visitor.visitModel(model);
ParsedTemplateV3 template = model.getTemplate();
visitor.visitTemplate(template);
visitCard(visitor, template);
for (ParsedGroupV3 group : model.determineGroups())
visitGroup(visitor, group);
for (ParsedButtonV3 button : model.determineButtons())
visitButton(visitor, button);
visitor.exitTemplate(template);
visitor.exitModel(model);
}
private static void visitCard(ParsedModel3Visitor visitor,
ParsedTemplateV3 template) {
CardUrlConfig cardUrlConfig = template.getCardUrlConfig();
if (cardUrlConfig != null && cardUrlConfig.getUrlConfig() != null) {
visitor.visitTemplateCardUrlConfig(cardUrlConfig.getUrlConfig());
visitor.exitTemplateCardUrlConfig(cardUrlConfig.getUrlConfig());
}
}
private static void visitGroup(ParsedModel3Visitor visitor, ParsedGroupV3 group) {
visitor.visitGroup(group);
ParsedGroupInfo groupInfo = group.getGroupInfo();
if (groupInfo != null) {
visitor.visitGroupInfo(group, groupInfo);
visitGroupKeyValues(visitor, group, groupInfo);
visitGroupDetail(visitor, group, groupInfo);
visitor.exitGroupInfo(group, groupInfo);
}
visitor.exitGroup(group);
}
private static void visitGroupKeyValues(ParsedModel3Visitor visitor,
ParsedGroupV3 group,
ParsedGroupInfo groupInfo) {
if (groupInfo.getKeyValues() == null) return;
for (ParsedKV kv : groupInfo.getKeyValues()) {
visitor.visitGroupKeyValue(group, kv);
visitor.exitGroupKeyValue(group, kv);
}
}
private static void visitGroupDetail(ParsedModel3Visitor visitor,
ParsedGroupV3 group,
ParsedGroupInfo groupInfo) {
if (groupInfo.getDetail() == null) return;
visitor.visitGroupDetail(group, groupInfo.getDetail());
if (groupInfo.getDetail().getUrlConfig() != null) {
visitor.visitGroupDetailUrl(group, groupInfo.getDetail().getUrlConfig());
visitor.exitGroupDetailUrl(group, groupInfo.getDetail().getUrlConfig());
}
visitor.exitGroupDetail(group, groupInfo.getDetail());
}
private static void visitButton(ParsedModel3Visitor visitor,
ParsedButtonV3 button) {
visitor.visitButton(button);
if (button.getUrlConfig() != null) {
visitor.visitButtonUrlConfig(button, button.getUrlConfig());
visitor.exitButtonUrlConfig(button, button.getUrlConfig());
}
visitor.exitButton(button);
}
}

View File

@ -1,42 +0,0 @@
package cn.axzo.msg.center.service.pending.response.v3;
import cn.axzo.msg.center.service.enums.GroupType;
import lombok.Getter;
import lombok.Setter;
import java.util.Collections;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* @author yanglin
*/
@Setter
@Getter
public class TodoModelV3 {
/**
* 分组
*/
private List<TodoGroupV3> groups;
/**
* 按钮
*/
private List<TodoButtonV3> buttons;
public List<TodoGroupV3> getGroups(GroupType type) {
return determineGroups().stream()
.filter(group -> group.getGroupType() == type)
.collect(toList());
}
public List<TodoGroupV3> determineGroups() {
return groups == null ? Collections.emptyList() : groups;
}
public List<TodoButtonV3> determineButtons() {
return buttons == null ? Collections.emptyList() : buttons;
}
}

View File

@ -0,0 +1,14 @@
package cn.axzo.msg.center.service.pending.response.v3.model;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author yanglin
*/
@Getter
@RequiredArgsConstructor
public class ComponentWorkerGroup {
private final ParsedGroupV3 group;
private final Long personId;
}

View File

@ -1,19 +1,24 @@
package cn.axzo.msg.center.service.pending.response.v3;
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.enums.ButtonStyleEnum;
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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import lombok.Getter;
import lombok.Setter;
import java.util.Collections;
import java.util.List;
/**
* @author yanglin
*/
@Setter
@Getter
public class TodoButtonV3 {
public class ParsedButtonV3 {
private Long id;
@ -72,4 +77,8 @@ public class TodoButtonV3 {
*/
private Integer priority;
public List<ButtonStyleEnum> parseStyle() {
if (style == null) return Collections.emptyList();
return JSON.parseArray(style.toJSONString(), ButtonStyleEnum.class);
}
}

View File

@ -0,0 +1,30 @@
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.msg.center.service.domain.DetailConfig;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author yanglin
*/
@Setter
@Getter
public class ParsedGroupInfo {
/**
* key/value的列表
*/
private List<ParsedKV> keyValues;
/**
* 详情的配置
*/
private DetailConfig detail;
public void removeEmptyValues() {
if (keyValues == null) return;
keyValues.removeIf(ParsedKV::isValueEmpty);
}
}

View File

@ -1,16 +1,19 @@
package cn.axzo.msg.center.service.pending.response.v3;
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.msg.center.service.domain.GroupConfig;
import cn.axzo.msg.center.service.enums.GroupType;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* @author yanglin
*/
@Setter
@Getter
public class TodoGroupV3 {
public class ParsedGroupV3 {
private Long id;
@ -29,7 +32,7 @@ public class TodoGroupV3 {
/**
* 分组信息. groupType=KV_VALUES读这个信息
*/
private GroupConfig groupInfo;
private ParsedGroupInfo groupInfo;
/**
* 工人卡片信息. groupType=COMPONENT_WORKER读这个信息
@ -38,4 +41,8 @@ public class TodoGroupV3 {
*/
private WorkerInfo workerInfo;
@NotNull
public List<ParsedKV> getKeyValues() {
return groupInfo == null ? Collections.emptyList() : groupInfo.getKeyValues();
}
}

View File

@ -0,0 +1,54 @@
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.msg.center.service.enums.KVContentType;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
/**
* @author yanglin
*/
@Setter
@Getter
public class ParsedKV {
/**
* 内容的类型. TEXT: 文本, PHONE: 手机号, ATTACHMENT: 附件, PERSON_ID: 自然人ID
*/
private KVContentType contentType;
/**
* : 项目
*/
private String key;
/**
*
*/
private String value;
/**
* 是否显示在卡片上
*/
private boolean displayOnCard;
public boolean isValueEmpty() {
return StringUtils.isBlank(value) || "null".equalsIgnoreCase(value);
}
public Long getValueAsLong() {
if (isValueEmpty())
return null;
if (!NumberUtils.isDigits(value))
return null;
return Long.parseLong(value);
}
// !! 额外信息
/**
* contentType=PERSON_ID时的人员信息, 由yoke填充
*/
private PersonInfo personInfo;
}

View File

@ -0,0 +1,78 @@
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.msg.center.service.enums.GroupType;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* @author yanglin
*/
@Setter
@Getter
public class ParsedModelV3 {
/**
* 模板. 对前端来说没用
*/
@JsonIgnore @JSONField(serialize = false)
private ParsedTemplateV3 template;
/**
* 分组
*/
private List<ParsedGroupV3> groups;
/**
* 按钮
*/
private List<ParsedButtonV3> buttons;
/**
* 前端忽略
*/
@JsonIgnore @JSONField(serialize = false)
private List<ParsedKV> personKeyValues = new ArrayList<>();
/**
* 前端忽略
*/
@JsonIgnore @JSONField(serialize = false)
private List<ComponentWorkerGroup> componentWorkerGroups = new ArrayList<>();
public void addPersonKV(ParsedKV kv) {
personKeyValues.add(kv);
}
public void addComponentWorkerGroup(ComponentWorkerGroup group) {
componentWorkerGroups.add(group);
}
public List<ParsedGroupV3> getGroups(GroupType type) {
return determineGroups().stream()
.filter(group -> group.getGroupType() == type)
.collect(toList());
}
public List<ParsedGroupV3> determineGroups() {
return groups == null ? Collections.emptyList() : groups;
}
public List<ParsedButtonV3> determineButtons() {
return buttons == null ? Collections.emptyList() : buttons;
}
public void removeEmptyKVGroups() {
groups.removeIf(g -> {
boolean isKVGroup = g.getGroupType() == GroupType.KV_VALUES;
return isKVGroup && g.getKeyValues().isEmpty();
});
}
}

View File

@ -0,0 +1,93 @@
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.msg.center.service.domain.CardUrlConfig;
import cn.axzo.msg.center.service.enums.CardUrlOpenStrategy;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.StatusEnum;
import cn.axzo.msg.center.service.enums.YesOrNo;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class ParsedTemplateV3 {
/**
* 模板名称
*/
private String name;
/**
* 系统自动生成的模板code
*/
private String code;
/**
* 所属消息类型
*/
private MessageCategoryEnum msgCategory;
/**
* 模板标题
*/
private String title;
/**
* 模板类容
*/
private String content;
/**
* 消息详情样式. BIZ_COMMON: 业务待办能用, FLOW_COMMON: 审批待办能用, 其它动态配置的
*/
private String detailStyleCode;
/**
* 模板icon
*/
private String icon;
/**
* APP最小版本支持可不配
*/
private String minAppVersion;
/**
* 模板状态
*/
private StatusEnum status;
/**
* 推送终端配置 JSON字串
*/
private String pushTerminal;
/**
* 卡片跳转方式. NONE: 无跳转, OPEN_TODO_DETAIL: 打开待办详情, OPEN_CUSTOM_PAGE: 打开指定页面
*/
private CardUrlOpenStrategy cardUrlOpenStrategy;
/**
* 卡片跳转配置. 在links的基础上再包一层, 避免以后卡片增加自己的配置
*/
private CardUrlConfig cardUrlConfig;
/**
* IM发送优先级
*/
private Integer imSendPriority;
/**
* push配置
*/
private JSONObject pushData;
/**
* 是否显示在列表中. YES: , NO:
*/
private YesOrNo displayOnList;
}

View File

@ -0,0 +1,33 @@
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.trade.datasecurity.sd.extension.annotation.SDCellPhoneField;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class PersonInfo {
/**
* 用户姓名
*/
private String realName;
/**
* 用户头像
*/
private String avatar;
/**
* 手机号, 未加密
*/
@SDCellPhoneField
private String mobilePhone;
/**
* 加密手机号
*/
private String mobilePhoneCiphertext;
}

View File

@ -1,4 +1,4 @@
package cn.axzo.msg.center.service.pending.response.v3;
package cn.axzo.msg.center.service.pending.response.v3.model;
import cn.axzo.trade.datasecurity.sd.extension.annotation.SDCellPhoneField;
import cn.axzo.trade.datasecurity.sd.extension.annotation.SDIdCardField;

View File

@ -25,7 +25,8 @@ import org.springframework.core.env.Environment;
"cn.axzo.pluto.api",
"cn.axzo.basics.profiles.api",
"cn.axzo.apollo.api",
"cn.axzo.msg.center.inside.notices.service.impl"
"cn.axzo.msg.center.inside.notices.service.impl",
"cn.axzo.meepo.api"
})
/*@EnableAsync*/
public class MsgCenterApplication {

View File

@ -1,40 +0,0 @@
package cn.axzo.msg.center.message.service.youmeng;
import cn.axzo.msg.center.MsgCenterApplication;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import com.google.common.util.concurrent.Uninterruptibles;
import lombok.RequiredArgsConstructor;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author yanglin
*/
@SpringBootTest(classes = MsgCenterApplication.class)
@RequiredArgsConstructor(onConstructor_ = @Autowired)
class YoumengTemplateClientTest {
private final YoumengTemplateClient youmengTemplateClient;
@Test
void foo() {
YoumengPush push = new YoumengPush();
push.setTitle("aaa");
push.setContent("bbb");
push.setReceiverOuId(3L);
push.setReceiverPersonId(444L);
YoumengPush.PushNavigation navigation = new YoumengPush.PushNavigation();
navigation.setUrl("test_url");
navigation.setPlatform(TerminalTypeEnum.ANDROID);
push.setNavigations(Collections.singletonList(navigation));
youmengTemplateClient.syncSend(590L, Collections.singletonList(push));
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.MINUTES);
}
}