feat: 新增消息推送初始化逻辑
This commit is contained in:
parent
2f92eeef1a
commit
dfca986d97
@ -0,0 +1,117 @@
|
||||
package com.yfd.platform.system.controller;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.yfd.platform.annotation.Log;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetRequest;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
import com.yfd.platform.system.service.IPushConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/system/pushConfig")
|
||||
@Tag(name = "推送配置")
|
||||
public class PushConfigController {
|
||||
|
||||
@Resource
|
||||
private IPushConfigService pushConfigService;
|
||||
|
||||
@Operation(summary = "查询推送配置列表")
|
||||
@GetMapping("/getPushConfigList")
|
||||
public ResponseResult getPushConfigList(Page<PushConfig> page,
|
||||
String categoryName,
|
||||
String messageType,
|
||||
Integer targetType,
|
||||
Integer status) {
|
||||
return ResponseResult.successData(pushConfigService.getPushConfigPage(page, categoryName, messageType, targetType, status));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据ID查询推送配置")
|
||||
@GetMapping("/getPushConfigById")
|
||||
public ResponseResult getPushConfigById(@RequestParam String id) {
|
||||
return ResponseResult.successData(pushConfigService.getById(id));
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "新增推送配置")
|
||||
@Operation(summary = "新增推送配置")
|
||||
@PostMapping("/addPushConfig")
|
||||
public ResponseResult addPushConfig(@RequestBody PushConfig pushConfig) {
|
||||
return pushConfigService.addPushConfig(pushConfig) ? ResponseResult.success() : ResponseResult.error("新增失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "修改推送配置")
|
||||
@Operation(summary = "修改推送配置")
|
||||
@PostMapping("/updatePushConfig")
|
||||
public ResponseResult updatePushConfig(@RequestBody PushConfig pushConfig) {
|
||||
return pushConfigService.updatePushConfig(pushConfig) ? ResponseResult.success() : ResponseResult.error("修改失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "删除推送配置")
|
||||
@Operation(summary = "删除推送配置")
|
||||
@PostMapping("/deletePushConfig")
|
||||
public ResponseResult deletePushConfig(@RequestParam String ids) {
|
||||
return pushConfigService.deletePushConfig(ids) ? ResponseResult.success() : ResponseResult.error("删除失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "设置推送配置状态")
|
||||
@Operation(summary = "设置推送配置状态")
|
||||
@PostMapping("/setPushConfigStatus")
|
||||
public ResponseResult setPushConfigStatus(@RequestParam String id, @RequestParam Integer status) {
|
||||
return pushConfigService.setPushConfigStatus(id, status) ? ResponseResult.success() : ResponseResult.error("设置失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "保存推送目标")
|
||||
@Operation(summary = "保存推送目标")
|
||||
@PostMapping("/savePushTargets")
|
||||
public ResponseResult savePushTargets(@RequestBody PushConfigTargetRequest request) {
|
||||
return pushConfigService.savePushTargets(request) ? ResponseResult.success() : ResponseResult.error("保存失败");
|
||||
}
|
||||
|
||||
@Operation(summary = "查询推送目标")
|
||||
@GetMapping("/getPushTargets")
|
||||
public ResponseResult getPushTargets(@RequestParam String configId) {
|
||||
return ResponseResult.successData(pushConfigService.getPushTargets(configId));
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "立即执行推送配置")
|
||||
@Operation(summary = "立即执行推送配置")
|
||||
@PostMapping("/execution")
|
||||
public ResponseResult execution(@RequestParam String configId) {
|
||||
return pushConfigService.executeNow(configId) ? ResponseResult.success() : ResponseResult.error("执行失败");
|
||||
}
|
||||
|
||||
@Operation(summary = "查询推送历史主表")
|
||||
@GetMapping("/getPushHistoryList")
|
||||
public ResponseResult getPushHistoryList(Page<PushHistory> page,
|
||||
String configId,
|
||||
Integer status,
|
||||
String messageTypeCode,
|
||||
String startTime,
|
||||
String endTime) {
|
||||
Date start = StrUtil.isBlank(startTime) ? null : DateUtil.parse(startTime);
|
||||
Date end = StrUtil.isBlank(endTime) ? null : DateUtil.parse(endTime);
|
||||
return ResponseResult.successData(pushConfigService.getPushHistoryPage(page, configId, status, messageTypeCode, start, end));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询推送历史明细")
|
||||
@GetMapping("/getPushHistoryDetailList")
|
||||
public ResponseResult getPushHistoryDetailList(Page<PushHistoryDetail> page,
|
||||
String historyId,
|
||||
Integer status) {
|
||||
return ResponseResult.successData(pushConfigService.getPushHistoryDetailPage(page, historyId, status));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_CONFIG")
|
||||
public class PushConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String categoryCode;
|
||||
|
||||
private String categoryName;
|
||||
|
||||
private String baseIdList;
|
||||
|
||||
private String baseNameList;
|
||||
|
||||
private String messageType;
|
||||
|
||||
private String cronExpression;
|
||||
|
||||
private Integer targetType;
|
||||
|
||||
private Integer isSms;
|
||||
|
||||
private Long pushCount;
|
||||
|
||||
private Long dailyPushCount;
|
||||
|
||||
private Date finishTime;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private Date updatedAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PushConfigTargetRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String configId;
|
||||
|
||||
/**
|
||||
* 0-用户,1-角色
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
private List<String> userRoleIds;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class PushConfigTargetVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private String configId;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private String userRoleId;
|
||||
|
||||
private String targetName;
|
||||
|
||||
private String targetPhone;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_CONFIG_USER")
|
||||
public class PushConfigUser implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String configId;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private String userRoleId;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_HISTORY")
|
||||
public class PushHistory implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String configId;
|
||||
|
||||
private Date planTime;
|
||||
|
||||
private String messageTypeCode;
|
||||
|
||||
private String messageTypeName;
|
||||
|
||||
private String title;
|
||||
|
||||
private String content;
|
||||
|
||||
private Long pushedCount;
|
||||
|
||||
private Long successCount;
|
||||
|
||||
private Long failCount;
|
||||
|
||||
private Long pendingCount;
|
||||
|
||||
private String sendChannel;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String source;
|
||||
|
||||
private String relation;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private Date updatedAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_HISTORY_DETAIL")
|
||||
public class PushHistoryDetail implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String historyId;
|
||||
|
||||
private String targetName;
|
||||
|
||||
private String targetPhone;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String sendChannel;
|
||||
|
||||
private Date sendTime;
|
||||
|
||||
private String errorMsg;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class PushTargetUserVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String userId;
|
||||
|
||||
private String targetName;
|
||||
|
||||
private String targetPhone;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
|
||||
public interface PushConfigMapper extends BaseMapper<PushConfig> {
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetVo;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
import com.yfd.platform.system.domain.PushTargetUserVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PushConfigUserMapper extends BaseMapper<PushConfigUser> {
|
||||
|
||||
List<PushTargetUserVo> selectAllActiveUsers();
|
||||
|
||||
List<PushTargetUserVo> selectTargetUsersByConfigId(@Param("configId") String configId);
|
||||
|
||||
List<PushConfigTargetVo> selectConfigTargets(@Param("configId") String configId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
|
||||
public interface PushHistoryDetailMapper extends BaseMapper<PushHistoryDetail> {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
|
||||
public interface PushHistoryMapper extends BaseMapper<PushHistory> {
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetRequest;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetVo;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface IPushConfigService extends IService<PushConfig> {
|
||||
|
||||
Page<PushConfig> getPushConfigPage(Page<PushConfig> page,
|
||||
String categoryName,
|
||||
String messageType,
|
||||
Integer targetType,
|
||||
Integer status);
|
||||
|
||||
boolean addPushConfig(PushConfig pushConfig);
|
||||
|
||||
boolean updatePushConfig(PushConfig pushConfig);
|
||||
|
||||
boolean deletePushConfig(String ids);
|
||||
|
||||
boolean setPushConfigStatus(String id, Integer status);
|
||||
|
||||
boolean savePushTargets(PushConfigTargetRequest request);
|
||||
|
||||
List<PushConfigTargetVo> getPushTargets(String configId);
|
||||
|
||||
Page<PushHistory> getPushHistoryPage(Page<PushHistory> page,
|
||||
String configId,
|
||||
Integer status,
|
||||
String messageTypeCode,
|
||||
Date startTime,
|
||||
Date endTime);
|
||||
|
||||
Page<PushHistoryDetail> getPushHistoryDetailPage(Page<PushHistoryDetail> page,
|
||||
String historyId,
|
||||
Integer status);
|
||||
|
||||
boolean executeNow(String configId);
|
||||
|
||||
void executePushConfig(String configId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
|
||||
public interface IPushConfigUserService extends IService<PushConfigUser> {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
|
||||
public interface IPushHistoryDetailService extends IService<PushHistoryDetail> {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
|
||||
public interface IPushHistoryService extends IService<PushHistory> {
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.yfd.platform.system.service.IPushConfigService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service("pushConfigQuartzExecutor")
|
||||
public class PushConfigQuartzExecutor {
|
||||
|
||||
@Resource
|
||||
private IPushConfigService pushConfigService;
|
||||
|
||||
public void execute(String configId) {
|
||||
pushConfigService.executePushConfig(configId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,463 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetRequest;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetVo;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
import com.yfd.platform.system.domain.PushTargetUserVo;
|
||||
import com.yfd.platform.system.domain.QuartzJob;
|
||||
import com.yfd.platform.system.mapper.PushConfigMapper;
|
||||
import com.yfd.platform.system.mapper.PushConfigUserMapper;
|
||||
import com.yfd.platform.system.service.IPushConfigService;
|
||||
import com.yfd.platform.system.service.IPushConfigUserService;
|
||||
import com.yfd.platform.system.service.IPushHistoryDetailService;
|
||||
import com.yfd.platform.system.service.IPushHistoryService;
|
||||
import com.yfd.platform.system.service.IQuartzJobService;
|
||||
import com.yfd.platform.utils.QuartzManage;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.quartz.CronExpression;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class PushConfigServiceImpl extends ServiceImpl<PushConfigMapper, PushConfig> implements IPushConfigService {
|
||||
|
||||
private static final String QUARTZ_BIZ_TYPE = "PUSH_CONFIG";
|
||||
private static final String DEFAULT_SEND_CHANNEL = "SMS";
|
||||
private static final String DEFAULT_SOURCE = "PUSH_CONFIG";
|
||||
|
||||
@Resource
|
||||
private PushConfigUserMapper pushConfigUserMapper;
|
||||
|
||||
@Resource
|
||||
private IPushConfigUserService pushConfigUserService;
|
||||
|
||||
@Resource
|
||||
private IPushHistoryService pushHistoryService;
|
||||
|
||||
@Resource
|
||||
private IPushHistoryDetailService pushHistoryDetailService;
|
||||
|
||||
@Resource
|
||||
private IQuartzJobService quartzJobService;
|
||||
|
||||
@Resource
|
||||
private QuartzManage quartzManage;
|
||||
|
||||
@Override
|
||||
public Page<PushConfig> getPushConfigPage(Page<PushConfig> page,
|
||||
String categoryName,
|
||||
String messageType,
|
||||
Integer targetType,
|
||||
Integer status) {
|
||||
LambdaQueryWrapper<PushConfig> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(PushConfig::getIsDeleted, 0)
|
||||
.like(StrUtil.isNotBlank(categoryName), PushConfig::getCategoryName, categoryName)
|
||||
.like(StrUtil.isNotBlank(messageType), PushConfig::getMessageType, messageType)
|
||||
.eq(targetType != null, PushConfig::getTargetType, targetType)
|
||||
.eq(status != null, PushConfig::getStatus, status)
|
||||
.orderByDesc(PushConfig::getUpdatedAt, PushConfig::getCreatedAt);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean addPushConfig(PushConfig pushConfig) {
|
||||
validatePushConfig(pushConfig, false);
|
||||
Date now = new Date();
|
||||
pushConfig.setCreatedAt(now);
|
||||
pushConfig.setUpdatedAt(now);
|
||||
pushConfig.setModifyTime(now);
|
||||
pushConfig.setRecordUser(currentUserIdOrSystem());
|
||||
pushConfig.setModifyUser(currentUserIdOrSystem());
|
||||
pushConfig.setIsDeleted(0);
|
||||
pushConfig.setStatus(pushConfig.getStatus() == null ? 1 : pushConfig.getStatus());
|
||||
pushConfig.setIsSms(pushConfig.getIsSms() == null ? 0 : pushConfig.getIsSms());
|
||||
pushConfig.setPushCount(pushConfig.getPushCount() == null ? 0L : pushConfig.getPushCount());
|
||||
pushConfig.setDailyPushCount(pushConfig.getDailyPushCount() == null ? 0L : pushConfig.getDailyPushCount());
|
||||
boolean saved = this.save(pushConfig);
|
||||
if (saved) {
|
||||
syncQuartzJob(pushConfig);
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updatePushConfig(PushConfig pushConfig) {
|
||||
validatePushConfig(pushConfig, true);
|
||||
PushConfig dbConfig = getAvailableConfig(pushConfig.getId());
|
||||
dbConfig.setCategoryCode(pushConfig.getCategoryCode());
|
||||
dbConfig.setCategoryName(pushConfig.getCategoryName());
|
||||
dbConfig.setBaseIdList(pushConfig.getBaseIdList());
|
||||
dbConfig.setBaseNameList(pushConfig.getBaseNameList());
|
||||
dbConfig.setMessageType(pushConfig.getMessageType());
|
||||
dbConfig.setCronExpression(pushConfig.getCronExpression());
|
||||
dbConfig.setTargetType(pushConfig.getTargetType());
|
||||
dbConfig.setIsSms(pushConfig.getIsSms() == null ? 0 : pushConfig.getIsSms());
|
||||
dbConfig.setStatus(pushConfig.getStatus() == null ? dbConfig.getStatus() : pushConfig.getStatus());
|
||||
dbConfig.setUpdatedAt(new Date());
|
||||
dbConfig.setModifyTime(new Date());
|
||||
dbConfig.setModifyUser(currentUserIdOrSystem());
|
||||
boolean updated = this.updateById(dbConfig);
|
||||
if (updated) {
|
||||
if (Objects.equals(dbConfig.getTargetType(), 1)) {
|
||||
softDeleteTargets(dbConfig.getId(), currentUserIdOrSystem(), new Date());
|
||||
}
|
||||
syncQuartzJob(dbConfig);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deletePushConfig(String ids) {
|
||||
if (StrUtil.isBlank(ids)) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
Date now = new Date();
|
||||
String userId = currentUserIdOrSystem();
|
||||
for (String id : ids.split(",")) {
|
||||
String configId = StrUtil.trim(id);
|
||||
if (StrUtil.isBlank(configId)) {
|
||||
continue;
|
||||
}
|
||||
PushConfig config = getAvailableConfig(configId);
|
||||
config.setIsDeleted(1);
|
||||
config.setDeleteUser(userId);
|
||||
config.setDeleteTime(now);
|
||||
config.setModifyUser(userId);
|
||||
config.setModifyTime(now);
|
||||
config.setUpdatedAt(now);
|
||||
this.updateById(config);
|
||||
softDeleteTargets(configId, userId, now);
|
||||
deleteQuartzJob(configId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean setPushConfigStatus(String id, Integer status) {
|
||||
if (StrUtil.isBlank(id) || status == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
PushConfig config = getAvailableConfig(id);
|
||||
config.setStatus(status);
|
||||
config.setUpdatedAt(new Date());
|
||||
config.setModifyTime(new Date());
|
||||
config.setModifyUser(currentUserIdOrSystem());
|
||||
boolean updated = this.updateById(config);
|
||||
if (updated) {
|
||||
syncQuartzJob(config);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean savePushTargets(PushConfigTargetRequest request) {
|
||||
validatePushTargetRequest(request);
|
||||
PushConfig config = getAvailableConfig(request.getConfigId());
|
||||
validateTargetTypeMatch(config.getTargetType(), request.getType());
|
||||
Date now = new Date();
|
||||
String userId = currentUserIdOrSystem();
|
||||
softDeleteTargets(config.getId(), userId, now);
|
||||
if (request.getUserRoleIds() == null || request.getUserRoleIds().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
List<PushConfigUser> list = new ArrayList<>();
|
||||
for (String userRoleId : request.getUserRoleIds()) {
|
||||
String targetId = StrUtil.trim(userRoleId);
|
||||
if (StrUtil.isBlank(targetId)) {
|
||||
continue;
|
||||
}
|
||||
PushConfigUser relation = new PushConfigUser();
|
||||
relation.setConfigId(config.getId());
|
||||
relation.setType(request.getType());
|
||||
relation.setUserRoleId(targetId);
|
||||
relation.setCreatedAt(now);
|
||||
relation.setRecordUser(userId);
|
||||
relation.setModifyUser(userId);
|
||||
relation.setModifyTime(now);
|
||||
relation.setIsDeleted(0);
|
||||
list.add(relation);
|
||||
}
|
||||
return list.isEmpty() || pushConfigUserService.saveBatch(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PushConfigTargetVo> getPushTargets(String configId) {
|
||||
if (StrUtil.isBlank(configId)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return pushConfigUserMapper.selectConfigTargets(configId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PushHistory> getPushHistoryPage(Page<PushHistory> page,
|
||||
String configId,
|
||||
Integer status,
|
||||
String messageTypeCode,
|
||||
Date startTime,
|
||||
Date endTime) {
|
||||
LambdaQueryWrapper<PushHistory> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(PushHistory::getIsDeleted, 0)
|
||||
.eq(StrUtil.isNotBlank(configId), PushHistory::getConfigId, configId)
|
||||
.eq(status != null, PushHistory::getStatus, status)
|
||||
.eq(StrUtil.isNotBlank(messageTypeCode), PushHistory::getMessageTypeCode, messageTypeCode)
|
||||
.ge(startTime != null, PushHistory::getPlanTime, startTime)
|
||||
.le(endTime != null, PushHistory::getPlanTime, endTime)
|
||||
.orderByDesc(PushHistory::getPlanTime, PushHistory::getCreatedAt);
|
||||
return pushHistoryService.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PushHistoryDetail> getPushHistoryDetailPage(Page<PushHistoryDetail> page,
|
||||
String historyId,
|
||||
Integer status) {
|
||||
LambdaQueryWrapper<PushHistoryDetail> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(PushHistoryDetail::getIsDeleted, 0)
|
||||
.eq(StrUtil.isNotBlank(historyId), PushHistoryDetail::getHistoryId, historyId)
|
||||
.eq(status != null, PushHistoryDetail::getStatus, status)
|
||||
.orderByDesc(PushHistoryDetail::getCreatedAt, PushHistoryDetail::getSendTime);
|
||||
return pushHistoryDetailService.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeNow(String configId) {
|
||||
executePushConfig(configId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void executePushConfig(String configId) {
|
||||
PushConfig config = getAvailableConfig(configId);
|
||||
List<PushTargetUserVo> targets = resolveTargets(config);
|
||||
Date now = new Date();
|
||||
String operator = currentUserIdOrSystem();
|
||||
|
||||
PushHistory history = new PushHistory();
|
||||
history.setConfigId(config.getId());
|
||||
history.setPlanTime(now);
|
||||
history.setMessageTypeCode(config.getCategoryCode());
|
||||
history.setMessageTypeName(config.getCategoryName());
|
||||
history.setTitle(buildDefaultTitle(config));
|
||||
history.setContent(buildDefaultContent(config));
|
||||
history.setPushedCount(0L);
|
||||
history.setSuccessCount(0L);
|
||||
history.setFailCount(0L);
|
||||
history.setPendingCount((long) targets.size());
|
||||
history.setSendChannel(DEFAULT_SEND_CHANNEL);
|
||||
history.setStatus(0);
|
||||
history.setSource(DEFAULT_SOURCE);
|
||||
history.setRelation(StrUtil.blankToDefault(config.getBaseNameList(), config.getCategoryName()));
|
||||
history.setCreatedAt(now);
|
||||
history.setUpdatedAt(now);
|
||||
history.setRecordUser(operator);
|
||||
history.setModifyUser(operator);
|
||||
history.setModifyTime(now);
|
||||
history.setIsDeleted(0);
|
||||
pushHistoryService.save(history);
|
||||
|
||||
if (!targets.isEmpty()) {
|
||||
List<PushHistoryDetail> detailList = new ArrayList<>();
|
||||
for (PushTargetUserVo target : targets) {
|
||||
PushHistoryDetail detail = new PushHistoryDetail();
|
||||
detail.setHistoryId(history.getId());
|
||||
detail.setTargetName(target.getTargetName());
|
||||
detail.setTargetPhone(target.getTargetPhone());
|
||||
detail.setStatus(0);
|
||||
detail.setSendChannel(DEFAULT_SEND_CHANNEL);
|
||||
detail.setCreatedAt(now);
|
||||
detail.setRecordUser(operator);
|
||||
detail.setModifyUser(operator);
|
||||
detail.setModifyTime(now);
|
||||
detail.setIsDeleted(0);
|
||||
detailList.add(detail);
|
||||
}
|
||||
pushHistoryDetailService.saveBatch(detailList);
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePushConfig(PushConfig pushConfig, boolean requireId) {
|
||||
if (pushConfig == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
if (requireId && StrUtil.isBlank(pushConfig.getId())) {
|
||||
throw new BizException("配置ID不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getCategoryCode())) {
|
||||
throw new BizException("消息类别编码不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getCategoryName())) {
|
||||
throw new BizException("消息类别名称不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getMessageType())) {
|
||||
throw new BizException("消息类型不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getCronExpression()) || !CronExpression.isValidExpression(pushConfig.getCronExpression())) {
|
||||
throw new BizException("cron表达式格式错误.");
|
||||
}
|
||||
if (pushConfig.getTargetType() == null || (pushConfig.getTargetType() != 1 && pushConfig.getTargetType() != 2 && pushConfig.getTargetType() != 3)) {
|
||||
throw new BizException("推送目标类型不正确.");
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePushTargetRequest(PushConfigTargetRequest request) {
|
||||
if (request == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(request.getConfigId())) {
|
||||
throw new BizException("推送配置ID不能为空.");
|
||||
}
|
||||
if (request.getType() == null || (request.getType() != 0 && request.getType() != 1)) {
|
||||
throw new BizException("绑定类型不正确.");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTargetTypeMatch(Integer targetType, Integer relationType) {
|
||||
if (targetType == null) {
|
||||
return;
|
||||
}
|
||||
if (targetType == 1) {
|
||||
throw new BizException("当前配置为所有人推送,无需绑定目标.");
|
||||
}
|
||||
if (targetType == 2 && !Objects.equals(relationType, 0)) {
|
||||
throw new BizException("按人推送只能绑定用户.");
|
||||
}
|
||||
if (targetType == 3 && !Objects.equals(relationType, 1)) {
|
||||
throw new BizException("按角色推送只能绑定角色.");
|
||||
}
|
||||
}
|
||||
|
||||
private PushConfig getAvailableConfig(String id) {
|
||||
List<PushConfig> list = this.list(new LambdaQueryWrapper<PushConfig>()
|
||||
.eq(PushConfig::getId, id)
|
||||
.eq(PushConfig::getIsDeleted, 0));
|
||||
PushConfig config = list.isEmpty() ? null : list.get(0);
|
||||
if (config == null) {
|
||||
throw new BizException("推送配置不存在.");
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private void softDeleteTargets(String configId, String userId, Date now) {
|
||||
LambdaUpdateWrapper<PushConfigUser> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(PushConfigUser::getConfigId, configId)
|
||||
.eq(PushConfigUser::getIsDeleted, 0)
|
||||
.set(PushConfigUser::getIsDeleted, 1)
|
||||
.set(PushConfigUser::getDeleteUser, userId)
|
||||
.set(PushConfigUser::getDeleteTime, now)
|
||||
.set(PushConfigUser::getModifyUser, userId)
|
||||
.set(PushConfigUser::getModifyTime, now);
|
||||
pushConfigUserService.update(updateWrapper);
|
||||
}
|
||||
|
||||
private void syncQuartzJob(PushConfig config) {
|
||||
QuartzJob quartzJob = getPushQuartzJob(config.getId());
|
||||
Date now = new Date();
|
||||
if (quartzJob == null) {
|
||||
quartzJob = new QuartzJob();
|
||||
quartzJob.setCustom1(QUARTZ_BIZ_TYPE);
|
||||
quartzJob.setCustom2(config.getId());
|
||||
}
|
||||
quartzJob.setJobName("推送配置-" + config.getCategoryName());
|
||||
quartzJob.setJobClass("pushConfigQuartzExecutor");
|
||||
quartzJob.setJobMethod("execute");
|
||||
quartzJob.setJobCron(config.getCronExpression());
|
||||
quartzJob.setJobParams(config.getId());
|
||||
quartzJob.setDescription("推送配置定时任务-" + config.getMessageType());
|
||||
quartzJob.setStatus(Objects.equals(config.getStatus(), 1) ? "1" : "0");
|
||||
quartzJob.setLastmodifier(currentUsernameOrSystem());
|
||||
quartzJob.setLastmodifydate(new java.sql.Timestamp(now.getTime()));
|
||||
if (StrUtil.isBlank(quartzJob.getId())) {
|
||||
quartzJobService.save(quartzJob);
|
||||
quartzManage.addJob(quartzJob);
|
||||
} else {
|
||||
quartzJobService.updateById(quartzJob);
|
||||
quartzManage.updateJobCron(quartzJob);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteQuartzJob(String configId) {
|
||||
QuartzJob quartzJob = getPushQuartzJob(configId);
|
||||
if (quartzJob != null) {
|
||||
quartzManage.deleteJob(quartzJob);
|
||||
quartzJobService.removeById(quartzJob.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private QuartzJob getPushQuartzJob(String configId) {
|
||||
List<QuartzJob> list = quartzJobService.list(new LambdaQueryWrapper<QuartzJob>()
|
||||
.eq(QuartzJob::getCustom1, QUARTZ_BIZ_TYPE)
|
||||
.eq(QuartzJob::getCustom2, configId));
|
||||
return list.isEmpty() ? null : list.get(0);
|
||||
}
|
||||
|
||||
private List<PushTargetUserVo> resolveTargets(PushConfig config) {
|
||||
List<PushTargetUserVo> rawTargets;
|
||||
if (Objects.equals(config.getTargetType(), 1)) {
|
||||
rawTargets = pushConfigUserMapper.selectAllActiveUsers();
|
||||
} else {
|
||||
rawTargets = pushConfigUserMapper.selectTargetUsersByConfigId(config.getId());
|
||||
}
|
||||
if (rawTargets == null || rawTargets.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<String, PushTargetUserVo> targetMap = new LinkedHashMap<>();
|
||||
for (PushTargetUserVo target : rawTargets) {
|
||||
if (target == null || StrUtil.isBlank(target.getUserId()) || StrUtil.isBlank(target.getTargetPhone())) {
|
||||
continue;
|
||||
}
|
||||
targetMap.putIfAbsent(target.getUserId(), target);
|
||||
}
|
||||
return new ArrayList<>(targetMap.values());
|
||||
}
|
||||
|
||||
private String buildDefaultTitle(PushConfig config) {
|
||||
return StrUtil.format("【{}】默认推送标题", StrUtil.blankToDefault(config.getCategoryName(), "消息通知"));
|
||||
}
|
||||
|
||||
private String buildDefaultContent(PushConfig config) {
|
||||
return StrUtil.format("【{}】默认推送内容,消息类型:{},执行时间:{}",
|
||||
StrUtil.blankToDefault(config.getCategoryName(), "消息通知"),
|
||||
StrUtil.blankToDefault(config.getMessageType(), "未配置"),
|
||||
DateUtil.formatDateTime(new Date()));
|
||||
}
|
||||
|
||||
private String currentUserIdOrSystem() {
|
||||
try {
|
||||
return SecurityUtils.getUserId();
|
||||
} catch (Exception ex) {
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
|
||||
private String currentUsernameOrSystem() {
|
||||
try {
|
||||
return SecurityUtils.getCurrentUsername();
|
||||
} catch (Exception ex) {
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
import com.yfd.platform.system.mapper.PushConfigUserMapper;
|
||||
import com.yfd.platform.system.service.IPushConfigUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PushConfigUserServiceImpl extends ServiceImpl<PushConfigUserMapper, PushConfigUser> implements IPushConfigUserService {
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
import com.yfd.platform.system.mapper.PushHistoryDetailMapper;
|
||||
import com.yfd.platform.system.service.IPushHistoryDetailService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PushHistoryDetailServiceImpl extends ServiceImpl<PushHistoryDetailMapper, PushHistoryDetail> implements IPushHistoryDetailService {
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.mapper.PushHistoryMapper;
|
||||
import com.yfd.platform.system.service.IPushHistoryService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PushHistoryServiceImpl extends ServiceImpl<PushHistoryMapper, PushHistory> implements IPushHistoryService {
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.yfd.platform.system.mapper.PushConfigUserMapper">
|
||||
|
||||
<select id="selectAllActiveUsers" resultType="com.yfd.platform.system.domain.PushTargetUserVo">
|
||||
SELECT
|
||||
u.ID AS userId,
|
||||
NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME)) AS targetName,
|
||||
u.PHONE AS targetPhone
|
||||
FROM SYS_USER u
|
||||
WHERE u.STATUS = 1
|
||||
AND u.PHONE IS NOT NULL
|
||||
AND TRIM(u.PHONE) IS NOT NULL
|
||||
</select>
|
||||
|
||||
<select id="selectTargetUsersByConfigId" resultType="com.yfd.platform.system.domain.PushTargetUserVo">
|
||||
SELECT DISTINCT
|
||||
t.userId,
|
||||
t.targetName,
|
||||
t.targetPhone
|
||||
FROM (
|
||||
SELECT
|
||||
u.ID AS userId,
|
||||
NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME)) AS targetName,
|
||||
u.PHONE AS targetPhone
|
||||
FROM PUSH_CONFIG_USER pcu
|
||||
INNER JOIN SYS_USER u ON u.ID = pcu.USER_ROLE_ID
|
||||
WHERE pcu.CONFIG_ID = #{configId}
|
||||
AND pcu.TYPE = 0
|
||||
AND NVL(pcu.IS_DELETED, 0) = 0
|
||||
AND u.STATUS = 1
|
||||
AND u.PHONE IS NOT NULL
|
||||
AND TRIM(u.PHONE) IS NOT NULL
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
u.ID AS userId,
|
||||
NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME)) AS targetName,
|
||||
u.PHONE AS targetPhone
|
||||
FROM PUSH_CONFIG_USER pcu
|
||||
INNER JOIN SYS_ROLE_USERS sru ON sru.ROLEID = pcu.USER_ROLE_ID
|
||||
INNER JOIN SYS_USER u ON u.ID = sru.USERID
|
||||
WHERE pcu.CONFIG_ID = #{configId}
|
||||
AND pcu.TYPE = 1
|
||||
AND NVL(pcu.IS_DELETED, 0) = 0
|
||||
AND u.STATUS = 1
|
||||
AND u.PHONE IS NOT NULL
|
||||
AND TRIM(u.PHONE) IS NOT NULL
|
||||
) t
|
||||
</select>
|
||||
|
||||
<select id="selectConfigTargets" resultType="com.yfd.platform.system.domain.PushConfigTargetVo">
|
||||
SELECT
|
||||
pcu.ID AS id,
|
||||
pcu.CONFIG_ID AS configId,
|
||||
pcu.TYPE AS type,
|
||||
pcu.USER_ROLE_ID AS userRoleId,
|
||||
CASE
|
||||
WHEN pcu.TYPE = 0 THEN NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME))
|
||||
ELSE r.ROLENAME
|
||||
END AS targetName,
|
||||
CASE
|
||||
WHEN pcu.TYPE = 0 THEN u.PHONE
|
||||
ELSE NULL
|
||||
END AS targetPhone
|
||||
FROM PUSH_CONFIG_USER pcu
|
||||
LEFT JOIN SYS_USER u ON pcu.TYPE = 0 AND u.ID = pcu.USER_ROLE_ID
|
||||
LEFT JOIN SYS_ROLE r ON pcu.TYPE = 1 AND r.ID = pcu.USER_ROLE_ID
|
||||
WHERE pcu.CONFIG_ID = #{configId}
|
||||
AND NVL(pcu.IS_DELETED, 0) = 0
|
||||
ORDER BY pcu.CREATED_AT DESC, pcu.ID DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue
Block a user