1、结构化调整;
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package com.njcn.msgpush.framework.common.biz.infra.logger;
|
||||
package com.njcn.msgpush.framework.common.biz.system.logger;
|
||||
|
||||
import com.njcn.msgpush.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.biz.system.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.enums.RpcConstants;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -11,11 +11,11 @@ import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿:fallbackFactory =
|
||||
@FeignClient(name = RpcConstants.SYSTEM_NAME)
|
||||
@Tag(name = "RPC 服务 - API 访问日志")
|
||||
public interface ApiAccessLogCommonApi {
|
||||
|
||||
String PREFIX = RpcConstants.INFRA_PREFIX + "/api-access-log";
|
||||
String PREFIX = RpcConstants.SYSTEM_PREFIX + "/api-access-log";
|
||||
|
||||
@PostMapping(PREFIX + "/create")
|
||||
@Operation(summary = "创建 API 访问日志")
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.njcn.msgpush.framework.common.biz.infra.logger;
|
||||
package com.njcn.msgpush.framework.common.biz.system.logger;
|
||||
|
||||
import com.njcn.msgpush.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.biz.system.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.enums.RpcConstants;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -11,11 +11,11 @@ import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿:fallbackFactory =
|
||||
@FeignClient(name = RpcConstants.SYSTEM_NAME)
|
||||
@Tag(name = "RPC 服务 - API 异常日志")
|
||||
public interface ApiErrorLogCommonApi {
|
||||
|
||||
String PREFIX = RpcConstants.INFRA_PREFIX + "/api-error-log";
|
||||
String PREFIX = RpcConstants.SYSTEM_PREFIX + "/api-error-log";
|
||||
|
||||
@PostMapping(PREFIX + "/create")
|
||||
@Operation(summary = "创建 API 异常日志")
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.njcn.msgpush.framework.common.biz.infra.logger.dto;
|
||||
package com.njcn.msgpush.framework.common.biz.system.logger.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.framework.common.biz.infra.logger.dto;
|
||||
package com.njcn.msgpush.framework.common.biz.system.logger.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.njcn.msgpush.module.push.client.factory;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 工厂侧通用辅助方法。
|
||||
*/
|
||||
public final class ProviderFactorySupport {
|
||||
|
||||
private ProviderFactorySupport() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 只要任一配置值为空白,就认为当前渠道配置不完整。
|
||||
*/
|
||||
public static boolean hasBlank(String... values) {
|
||||
if (values == null || values.length == 0) {
|
||||
return true;
|
||||
}
|
||||
for (String value : values) {
|
||||
if (StrUtil.isBlank(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.njcn.msgpush.module.push.client.sender;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 发送结果大类。
|
||||
* 这里只描述“主流程该怎么走”,不承载第三方原始错误细节。
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SendOutcome {
|
||||
SUCCESS("发送成功"),
|
||||
ACCEPTED("第三方已受理"),
|
||||
FAILED("发送失败"),
|
||||
RETRYABLE_FAILED("发送失败,可重试"),
|
||||
UNSUPPORTED_CHANNEL("当前服务商不支持该发送渠道"),
|
||||
CONFIG_INVALID("当前服务商渠道配置不完整");
|
||||
|
||||
private final String desc;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.njcn.msgpush.module.push.client.sender;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 统一发送结果。
|
||||
* outcome 负责主流程分支判断;
|
||||
* errorCode/message 负责平台内部归类和中文展示;
|
||||
* retryable 负责决定是否进入重试队列。
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SendResult {
|
||||
|
||||
/**
|
||||
* 结果分类,供主流程分支判断使用。
|
||||
*/
|
||||
private SendOutcome outcome;
|
||||
|
||||
/**
|
||||
* 平台统一错误码。
|
||||
*/
|
||||
private String errorCode;
|
||||
|
||||
/**
|
||||
* 中文错误说明。
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 服务商原始错误码。
|
||||
*/
|
||||
private String providerRawCode;
|
||||
|
||||
/**
|
||||
* 是否允许进入重试队列。
|
||||
*/
|
||||
private boolean retryable;
|
||||
|
||||
/**
|
||||
* 第三方消息 ID。
|
||||
*/
|
||||
private String thirdPartyId;
|
||||
|
||||
/**
|
||||
* 发送时间。
|
||||
*/
|
||||
private LocalDateTime sendTime;
|
||||
|
||||
/**
|
||||
* 耗时,单位毫秒。
|
||||
*/
|
||||
private Integer costTime;
|
||||
|
||||
/**
|
||||
* 第三方已明确返回成功。
|
||||
*/
|
||||
public static SendResult success(LocalDateTime sendTime, Integer costTime, String thirdPartyId) {
|
||||
return SendResult.builder()
|
||||
.outcome(SendOutcome.SUCCESS)
|
||||
.sendTime(sendTime)
|
||||
.costTime(costTime)
|
||||
.thirdPartyId(thirdPartyId)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方已受理,请等待异步回执或延迟查询更新最终状态。
|
||||
*/
|
||||
public static SendResult accepted(LocalDateTime sendTime, Integer costTime, String thirdPartyId) {
|
||||
return SendResult.builder()
|
||||
.outcome(SendOutcome.ACCEPTED)
|
||||
.sendTime(sendTime)
|
||||
.costTime(costTime)
|
||||
.thirdPartyId(thirdPartyId)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务商不支持该渠道能力。
|
||||
*/
|
||||
public static SendResult unsupported(String message) {
|
||||
return SendResult.builder()
|
||||
.outcome(SendOutcome.UNSUPPORTED_CHANNEL)
|
||||
.errorCode("UNSUPPORTED_CHANNEL")
|
||||
.message(message)
|
||||
.retryable(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务商理论支持该能力,但当前配置不完整或初始化失败。
|
||||
*/
|
||||
public static SendResult configInvalid(String message) {
|
||||
return SendResult.builder()
|
||||
.outcome(SendOutcome.CONFIG_INVALID)
|
||||
.errorCode("CONFIG_INVALID")
|
||||
.message(message)
|
||||
.retryable(false)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.fallback;
|
||||
|
||||
import com.njcn.msgpush.module.push.client.sender.SendOutcome;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
|
||||
/**
|
||||
* 用于承载“发送前即可确定”的固定结果。
|
||||
* 例如:当前服务商不支持该渠道,或当前渠道配置不完整。
|
||||
*/
|
||||
public abstract class AbstractFixedResultSender {
|
||||
|
||||
private final SendOutcome outcome;
|
||||
|
||||
private final String message;
|
||||
|
||||
protected AbstractFixedResultSender(SendOutcome outcome, String message) {
|
||||
if (!SendOutcome.UNSUPPORTED_CHANNEL.equals(outcome) && !SendOutcome.CONFIG_INVALID.equals(outcome)) {
|
||||
throw new IllegalArgumentException("固定结果 sender 仅支持不支持渠道或配置无效场景");
|
||||
}
|
||||
this.outcome = outcome;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
protected SendResult buildResult() {
|
||||
if (SendOutcome.UNSUPPORTED_CHANNEL.equals(outcome)) {
|
||||
return SendResult.unsupported(message);
|
||||
}
|
||||
return SendResult.configInvalid(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.fallback;
|
||||
|
||||
import com.njcn.msgpush.module.push.client.sender.AppPushSender;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendOutcome;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
|
||||
/**
|
||||
* APP 推送渠道固定结果 sender。
|
||||
*/
|
||||
public class FixedResultAppPushSender extends AbstractFixedResultSender implements AppPushSender {
|
||||
|
||||
public FixedResultAppPushSender(SendOutcome outcome, String message) {
|
||||
super(outcome, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult appPush(MessageRecordDO messageRecord) {
|
||||
return this.buildResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.fallback;
|
||||
|
||||
import com.njcn.msgpush.module.push.client.sender.EmailSender;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendOutcome;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 邮件渠道固定结果 sender。
|
||||
*/
|
||||
public class FixedResultEmailSender extends AbstractFixedResultSender implements EmailSender {
|
||||
|
||||
public FixedResultEmailSender(SendOutcome outcome, String message) {
|
||||
super(outcome, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult sendEmail(MessageRecordDO messageRecord, Map<String, Object> params) {
|
||||
return this.buildResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.fallback;
|
||||
|
||||
import com.njcn.msgpush.module.push.client.sender.SendOutcome;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.client.sender.SmsSender;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信渠道固定结果 sender。
|
||||
* 用于替代返回 null,让主流程始终拿到可执行对象。
|
||||
*/
|
||||
public class FixedResultSmsSender extends AbstractFixedResultSender implements SmsSender {
|
||||
|
||||
public FixedResultSmsSender(SendOutcome outcome, String message) {
|
||||
super(outcome, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult sendSms(MessageRecordDO messageRecord) {
|
||||
return this.buildResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SendResult> sendBatchSms(List<MessageRecordDO> messageList) {
|
||||
List<SendResult> results = new ArrayList<>(messageList.size());
|
||||
for (int i = 0; i < messageList.size(); i++) {
|
||||
results.add(this.buildResult());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryTemplate(String templateIdentifier) {
|
||||
// 固定结果 sender 不触达第三方,无需查询模板。
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.impl.apppush;
|
||||
|
||||
import com.getui.push.v2.sdk.ApiHelper;
|
||||
import com.getui.push.v2.sdk.GtApiConfiguration;
|
||||
import com.getui.push.v2.sdk.api.PushApi;
|
||||
import com.getui.push.v2.sdk.common.ApiResult;
|
||||
import com.getui.push.v2.sdk.dto.req.Audience;
|
||||
import com.getui.push.v2.sdk.dto.req.Settings;
|
||||
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
|
||||
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
|
||||
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
|
||||
import com.njcn.msgpush.module.push.client.sender.AppPushSender;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.client.sender.Sender;
|
||||
import com.njcn.msgpush.module.push.client.setting.impl.UniPushAppPushSetting;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class UniPushAppPushSender implements AppPushSender {
|
||||
|
||||
private final Sender sender;
|
||||
|
||||
private PushApi pushApi;
|
||||
|
||||
public UniPushAppPushSender(UniPushAppPushSetting uniPushAppPushSetting, Sender sender) {
|
||||
this.sender = sender;
|
||||
try {
|
||||
GtApiConfiguration gtApiConfiguration = new GtApiConfiguration();
|
||||
gtApiConfiguration.setAppId(uniPushAppPushSetting.getAppId());
|
||||
gtApiConfiguration.setAppKey(uniPushAppPushSetting.getAppKey());
|
||||
gtApiConfiguration.setMasterSecret(uniPushAppPushSetting.getMasterSecret());
|
||||
gtApiConfiguration.setDomain("https://restapi.getui.com/v2/");
|
||||
ApiHelper apiHelper = ApiHelper.build(gtApiConfiguration);
|
||||
this.pushApi = apiHelper.creatApi(PushApi.class);
|
||||
} catch (Exception e) {
|
||||
log.error("UniPush 客户端初始化失败", e);
|
||||
this.pushApi = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult appPush(MessageRecordDO message) {
|
||||
if (pushApi == null) {
|
||||
return SendResult.configInvalid("当前服务商 APP 推送渠道初始化失败");
|
||||
}
|
||||
try {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long start = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
PushDTO<Audience> pushDTO = this.buildPushDTO(message.getTitle(), message.getContent());
|
||||
Audience audience = new Audience();
|
||||
audience.addCid(message.getReceiver());
|
||||
pushDTO.setAudience(audience);
|
||||
|
||||
ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushToSingleByCid(pushDTO);
|
||||
LocalDateTime end = LocalDateTime.now();
|
||||
int costTime = (int) (end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - start);
|
||||
message.setSendTime(now);
|
||||
message.setCostTime(costTime);
|
||||
|
||||
if (apiResult.isSuccess()) {
|
||||
// UniPush 同步接口返回成功时,当前平台将其视为已受理。
|
||||
return SendResult.accepted(now, costTime, null);
|
||||
}
|
||||
// 个推原始错误码在这里统一映射为平台错误码和中文错误信息。
|
||||
return this.sender.buildFailureResult(
|
||||
message,
|
||||
String.valueOf(apiResult.getCode()),
|
||||
apiResult.getMsg(),
|
||||
"THIRD_PARTY_CALL_FAILED",
|
||||
"第三方服务调用失败",
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("UniPush 推送失败", e);
|
||||
return this.sender.buildCallFailedResult("第三方服务调用失败");
|
||||
}
|
||||
}
|
||||
|
||||
private PushDTO<Audience> buildPushDTO(String title, String content) {
|
||||
PushDTO<Audience> pushDTO = new PushDTO<>();
|
||||
pushDTO.setRequestId(String.valueOf(System.currentTimeMillis()));
|
||||
|
||||
Settings settings = new Settings();
|
||||
settings.setTtl(3600000);
|
||||
pushDTO.setSettings(settings);
|
||||
|
||||
PushMessage pushMessage = new PushMessage();
|
||||
GTNotification notification = new GTNotification();
|
||||
notification.setTitle(title);
|
||||
notification.setBody(content);
|
||||
notification.setClickType("startapp");
|
||||
pushMessage.setNotification(notification);
|
||||
pushDTO.setPushMessage(pushMessage);
|
||||
return pushDTO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.impl.email;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyun.dm20151123.Client;
|
||||
import com.aliyun.dm20151123.models.SingleSendMailRequest;
|
||||
import com.aliyun.dm20151123.models.SingleSendMailResponse;
|
||||
import com.aliyun.teaopenapi.models.Config;
|
||||
import com.aliyun.teautil.models.RuntimeOptions;
|
||||
import com.njcn.msgpush.module.push.client.sender.EmailSender;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.client.sender.Sender;
|
||||
import com.njcn.msgpush.module.push.client.setting.impl.AliYunMailSetting;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
public class AliyunEmailSender implements EmailSender {
|
||||
|
||||
private static final String ACCOUNT_NAME = "accountName";
|
||||
private static final String REPLY_TO_ADDRESS = "replyToAddress";
|
||||
private static final String FROM_ALIAS = "fromAlias";
|
||||
|
||||
private final Sender sender;
|
||||
|
||||
private Client emailClient;
|
||||
|
||||
public AliyunEmailSender(AliYunMailSetting aliYunMailSetting, Sender sender) {
|
||||
this.sender = sender;
|
||||
if (ObjectUtil.isNotNull(aliYunMailSetting)) {
|
||||
Config config = new Config()
|
||||
.setAccessKeyId(aliYunMailSetting.getAccessKeyId())
|
||||
.setAccessKeySecret(aliYunMailSetting.getAccessKeySecret())
|
||||
.setRegionId(aliYunMailSetting.getRegionId())
|
||||
.setEndpoint(aliYunMailSetting.getEndpoint());
|
||||
|
||||
try {
|
||||
this.emailClient = new Client(config);
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云邮件客户端初始化失败", e);
|
||||
this.emailClient = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult sendEmail(MessageRecordDO message, Map<String, Object> params) {
|
||||
if (emailClient == null) {
|
||||
return SendResult.configInvalid("当前服务商邮件渠道初始化失败");
|
||||
}
|
||||
Future<SendResult> future = this.sender.MSG_PUSH_THREAD_POOL_EXECUTOR.submit(() -> {
|
||||
RuntimeOptions runtimeOptions = new RuntimeOptions();
|
||||
runtimeOptions.autoretry = true;
|
||||
|
||||
JSONObject jsonObject = JSON.parseObject(message.getExtraInfo());
|
||||
SingleSendMailRequest request = new SingleSendMailRequest()
|
||||
.setAccountName(jsonObject.getString(ACCOUNT_NAME))
|
||||
.setAddressType(1)
|
||||
.setReplyToAddress(jsonObject.getBooleanValue(REPLY_TO_ADDRESS))
|
||||
.setToAddress(message.getReceiver())
|
||||
.setSubject(message.getTitle())
|
||||
.setHtmlBody(message.getContent())
|
||||
.setTextBody("")
|
||||
.setFromAlias(jsonObject.getString(FROM_ALIAS));
|
||||
|
||||
try {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long start = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
SingleSendMailResponse response = this.emailClient.singleSendMailWithOptions(request, runtimeOptions);
|
||||
LocalDateTime end = LocalDateTime.now();
|
||||
int costTime = (int) (end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - start);
|
||||
message.setSendTime(now);
|
||||
message.setCostTime(costTime);
|
||||
|
||||
if (HttpStatus.OK.value() == response.getStatusCode()) {
|
||||
// 邮件接口同步返回成功时,当前平台直接认定本次发送成功。
|
||||
return SendResult.success(now, costTime, null);
|
||||
}
|
||||
|
||||
// 邮件服务失败同样统一转换为平台错误码和中文错误信息。
|
||||
return this.sender.buildFailureResult(
|
||||
message,
|
||||
String.valueOf(response.getStatusCode()),
|
||||
null,
|
||||
"THIRD_PARTY_CALL_FAILED",
|
||||
"第三方服务调用失败",
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云邮件发送失败", e);
|
||||
return this.sender.buildCallFailedResult("第三方服务调用失败");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return future.get(3, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云邮件发送超时或执行异常", e);
|
||||
return this.sender.buildTimeoutResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.impl.sms;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.aliyun.dysmsapi20170525.Client;
|
||||
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsRequest;
|
||||
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsResponse;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
|
||||
import com.aliyun.teaopenapi.models.Config;
|
||||
import com.aliyun.teautil.models.RuntimeOptions;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.client.sender.Sender;
|
||||
import com.njcn.msgpush.module.push.client.sender.SmsSender;
|
||||
import com.njcn.msgpush.module.push.client.setting.impl.AliYunMailSetting;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
public class AliyunSmsSender implements SmsSender {
|
||||
|
||||
public static final String OK = "OK";
|
||||
|
||||
private final Sender sender;
|
||||
|
||||
private Client smsClient;
|
||||
|
||||
public AliyunSmsSender(AliYunMailSetting aliYunSmsSetting, Sender sender) {
|
||||
this.sender = sender;
|
||||
if (ObjectUtil.isNotNull(aliYunSmsSetting)) {
|
||||
Config config = new Config()
|
||||
.setAccessKeyId(aliYunSmsSetting.getAccessKeyId())
|
||||
.setAccessKeySecret(aliYunSmsSetting.getAccessKeySecret())
|
||||
.setRegionId(aliYunSmsSetting.getRegionId())
|
||||
.setEndpoint(aliYunSmsSetting.getEndpoint());
|
||||
try {
|
||||
this.smsClient = new Client(config);
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云短信客户端初始化失败", e);
|
||||
this.smsClient = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult sendSms(MessageRecordDO message) {
|
||||
if (smsClient == null) {
|
||||
return SendResult.configInvalid("当前服务商短信渠道初始化失败");
|
||||
}
|
||||
Future<SendResult> future = this.sender.MSG_PUSH_THREAD_POOL_EXECUTOR.submit(() -> {
|
||||
RuntimeOptions runtimeOptions = new RuntimeOptions();
|
||||
runtimeOptions.autoretry = true;
|
||||
SendSmsRequest request = new SendSmsRequest()
|
||||
.setPhoneNumbers(message.getReceiver())
|
||||
.setSignName(message.getTitle())
|
||||
.setTemplateCode(message.getTemplateCode())
|
||||
.setTemplateParam(message.getTemplateParams());
|
||||
try {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long start = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
SendSmsResponse response = this.smsClient.sendSmsWithOptions(request, runtimeOptions);
|
||||
LocalDateTime end = LocalDateTime.now();
|
||||
int costTime = (int) (end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - start);
|
||||
message.setSendTime(now);
|
||||
message.setCostTime(costTime);
|
||||
if (HttpStatus.OK.value() == response.getStatusCode() && response.getBody() != null && OK.equals(response.getBody().getCode())) {
|
||||
String bizId = response.getBody().getBizId();
|
||||
message.setThirdPartyId(bizId);
|
||||
// 阿里云短信同步接口只表示“已受理”,最终是否送达依赖后续回执查询。
|
||||
this.getDownInfo(bizId, message);
|
||||
return SendResult.accepted(now, costTime, bizId);
|
||||
}
|
||||
String providerRawCode = response.getBody() == null ? null : response.getBody().getCode();
|
||||
String providerRawMessage = response.getBody() == null ? null : response.getBody().getMessage();
|
||||
// 第三方失败统一在这里映射为平台错误码和中文错误信息。
|
||||
return this.sender.buildFailureResult(
|
||||
message,
|
||||
providerRawCode,
|
||||
providerRawMessage,
|
||||
"THIRD_PARTY_CALL_FAILED",
|
||||
"第三方服务调用失败",
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云短信发送失败", e);
|
||||
return this.sender.buildCallFailedResult("第三方服务调用失败");
|
||||
}
|
||||
});
|
||||
try {
|
||||
return future.get(3, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云短信发送超时或执行异常", e);
|
||||
return this.sender.buildTimeoutResult();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SendResult> sendBatchSms(List<MessageRecordDO> messageList) {
|
||||
List<SendResult> results = new ArrayList<>();
|
||||
for (MessageRecordDO message : messageList) {
|
||||
results.add(this.sendSms(message));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryTemplate(String templateIdentifier) {
|
||||
}
|
||||
|
||||
private void getDownInfo(String bizId, MessageRecordDO message) {
|
||||
// 回执存在延迟,这里延后查询,避免刚发送完就拿不到最终状态。
|
||||
this.sender.MSG_CALLBACK_THREAD_POOL_SCHEDULER.schedule(() -> {
|
||||
QuerySendDetailsRequest request = new QuerySendDetailsRequest()
|
||||
.setPhoneNumber(message.getReceiver())
|
||||
.setBizId(bizId)
|
||||
.setSendDate(message.getSendTime().format(DateTimeFormatter.ofPattern("yyyyMMdd")))
|
||||
.setCurrentPage(1L)
|
||||
.setPageSize(10L);
|
||||
try {
|
||||
QuerySendDetailsResponse response = this.smsClient.querySendDetails(request);
|
||||
if (response.getBody() == null || response.getBody().getSmsSendDetailDTOs() == null || response.getBody().getSmsSendDetailDTOs().getSmsSendDetailDTO() == null) {
|
||||
return;
|
||||
}
|
||||
response.getBody().getSmsSendDetailDTOs().getSmsSendDetailDTO().forEach(detail -> {
|
||||
if (!"DELIVERED".equals(detail.getErrCode())) {
|
||||
SendResult failedResult = this.sender.buildFailureResult(
|
||||
message,
|
||||
detail.getErrCode(),
|
||||
null,
|
||||
"THIRD_PARTY_CALLBACK_FAILED",
|
||||
"短信回执返回失败",
|
||||
false
|
||||
);
|
||||
this.sender.applyCallbackResult(message, failedResult);
|
||||
} else {
|
||||
// 送达成功后,统一复用主流程成功状态更新逻辑。
|
||||
this.sender.applyCallbackResult(
|
||||
message,
|
||||
SendResult.success(message.getSendTime(), message.getCostTime(), message.getThirdPartyId())
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云短信回执查询失败", e);
|
||||
}
|
||||
}, 20, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package com.njcn.msgpush.module.push.client.sender.impl.sms;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.njcn.msgpush.module.push.client.sender.SendResult;
|
||||
import com.njcn.msgpush.module.push.client.sender.Sender;
|
||||
import com.njcn.msgpush.module.push.client.sender.SmsSender;
|
||||
import com.njcn.msgpush.module.push.client.setting.impl.TelecomSmsSetting;
|
||||
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.alibaba.fastjson.JSON.toJSON;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
public class TelecomSmsSender implements SmsSender {
|
||||
|
||||
private static final String CONTENT_TYPE = "application/json;charset=utf-8";
|
||||
|
||||
private final TelecomSmsSetting telecomSmsSetting;
|
||||
private final Sender sender;
|
||||
|
||||
@Data
|
||||
private static class TelecomSmsSendResponse {
|
||||
private String status;
|
||||
private Double balance;
|
||||
private List<TelecomSmsSendDetailRes> list;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class TelecomSmsSendDetailRes {
|
||||
private String mid;
|
||||
private String mobile;
|
||||
private Integer result;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class TelecomSmsSelectResponse {
|
||||
private String status;
|
||||
private Double balance;
|
||||
private List<TelecomSmsSelectDetailRes> list;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class TelecomSmsSelectDetailRes {
|
||||
private String apmid;
|
||||
private String apSubmitTime;
|
||||
private String mobile;
|
||||
private Integer status;
|
||||
private String stat;
|
||||
private String deliverTime;
|
||||
}
|
||||
|
||||
public TelecomSmsSender(TelecomSmsSetting telecomSmsSetting, Sender sender) {
|
||||
this.telecomSmsSetting = telecomSmsSetting;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult sendSms(MessageRecordDO message) {
|
||||
Future<SendResult> future = this.sender.MSG_PUSH_THREAD_POOL_EXECUTOR.submit(() -> {
|
||||
Map<String, Object> request = new HashMap<>();
|
||||
boolean isTemplateSend = StrUtil.isNotBlank(message.getTemplateCode());
|
||||
request.put("account", telecomSmsSetting.getAccount());
|
||||
request.put("password", telecomSmsSetting.getPassword());
|
||||
request.put("extno", telecomSmsSetting.getExtno());
|
||||
if (isTemplateSend) {
|
||||
request.put("action", "templatep2p");
|
||||
Map<String, Object> templateJsonMap = new HashMap<>();
|
||||
templateJsonMap.put("templateID", message.getTemplateCode());
|
||||
JSONObject jsonObject = JSON.parseObject(message.getTemplateParams());
|
||||
Map<String, String> variable = new HashMap<>();
|
||||
variable.put("mobile", message.getReceiver());
|
||||
jsonObject.forEach((key, value) -> variable.put(key, value.toString()));
|
||||
templateJsonMap.put("variable", "[" + toJSON(variable) + "]");
|
||||
request.put("templateJson", toJSON(templateJsonMap));
|
||||
} else {
|
||||
request.put("action", "send");
|
||||
request.put("mobile", message.getReceiver());
|
||||
request.put("content", message.getContent());
|
||||
}
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Content-Type", CONTENT_TYPE);
|
||||
|
||||
try {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long start = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
ResponseEntity<String> response = this.sender.restTemplateUtil.post(
|
||||
telecomSmsSetting.getApiUrl(),
|
||||
request,
|
||||
headers,
|
||||
String.class
|
||||
);
|
||||
LocalDateTime end = LocalDateTime.now();
|
||||
int costTime = (int) (end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - start);
|
||||
message.setSendTime(now);
|
||||
message.setCostTime(costTime);
|
||||
TelecomSmsSendResponse sendResponse = JSON.parseObject(response.getBody(), TelecomSmsSendResponse.class);
|
||||
TelecomSmsSendDetailRes detailRes = sendResponse == null || sendResponse.getList() == null || sendResponse.getList().isEmpty()
|
||||
? null
|
||||
: sendResponse.getList().get(0);
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK && detailRes != null && detailRes.getResult() != null && detailRes.getResult() == 0) {
|
||||
message.setThirdPartyId(detailRes.getMid());
|
||||
// 电信短信同步返回成功同样只代表已受理,最终状态以后续回执为准。
|
||||
this.getDownInfo(detailRes.getMid(), message);
|
||||
return SendResult.accepted(now, costTime, detailRes.getMid());
|
||||
}
|
||||
|
||||
String providerRawCode = detailRes == null || detailRes.getResult() == null ? null : String.valueOf(detailRes.getResult());
|
||||
// 电信原始结果码在这里统一映射为平台错误码和中文错误信息。
|
||||
return this.sender.buildFailureResult(
|
||||
message,
|
||||
providerRawCode,
|
||||
null,
|
||||
"THIRD_PARTY_CALL_FAILED",
|
||||
"第三方服务调用失败",
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("电信短信发送失败", e);
|
||||
return this.sender.buildCallFailedResult("第三方服务调用失败");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return future.get(3, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
log.error("电信短信发送超时或执行异常", e);
|
||||
return this.sender.buildTimeoutResult();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SendResult> sendBatchSms(List<MessageRecordDO> messageList) {
|
||||
List<SendResult> results = new ArrayList<>();
|
||||
for (MessageRecordDO message : messageList) {
|
||||
results.add(this.sendSms(message));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryTemplate(String templateIdentifier) {
|
||||
Map<String, Object> request = new HashMap<>();
|
||||
request.put("action", "templateSelect");
|
||||
request.put("account", telecomSmsSetting.getAccount());
|
||||
request.put("password", telecomSmsSetting.getPassword());
|
||||
request.put("templateJson", StrUtil.isBlank(templateIdentifier) ? 0 : templateIdentifier);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Content-Type", CONTENT_TYPE);
|
||||
this.sender.restTemplateUtil.post(
|
||||
telecomSmsSetting.getApiUrl(),
|
||||
request,
|
||||
headers,
|
||||
String.class
|
||||
);
|
||||
}
|
||||
|
||||
private void getDownInfo(String mid, MessageRecordDO message) {
|
||||
// 回执查询延后执行,给第三方落库和状态变更留出时间。
|
||||
this.sender.MSG_CALLBACK_THREAD_POOL_SCHEDULER.schedule(() -> {
|
||||
Map<String, Object> request = new HashMap<>();
|
||||
request.put("action", "select");
|
||||
request.put("account", telecomSmsSetting.getAccount());
|
||||
request.put("password", telecomSmsSetting.getPassword());
|
||||
request.put("date", message.getSendTime().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
|
||||
request.put("condition", "APMID");
|
||||
request.put("valueList", mid);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Content-Type", CONTENT_TYPE);
|
||||
try {
|
||||
ResponseEntity<String> response = this.sender.restTemplateUtil.post(
|
||||
telecomSmsSetting.getApiUrl(),
|
||||
request,
|
||||
headers,
|
||||
String.class
|
||||
);
|
||||
|
||||
TelecomSmsSelectResponse selectResponse = JSON.parseObject(response.getBody(), TelecomSmsSelectResponse.class);
|
||||
if (selectResponse == null || selectResponse.getList() == null || selectResponse.getList().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
TelecomSmsSelectDetailRes detailRes = selectResponse.getList().get(0);
|
||||
if (detailRes.getStatus() == 5) {
|
||||
SendResult failedResult = this.sender.buildFailureResult(
|
||||
message,
|
||||
detailRes.getStat(),
|
||||
null,
|
||||
"THIRD_PARTY_CALLBACK_FAILED",
|
||||
"短信回执返回失败",
|
||||
false
|
||||
);
|
||||
this.sender.applyCallbackResult(message, failedResult);
|
||||
} else if (detailRes.getStatus() == 4) {
|
||||
// 回执确认成功后,复用统一成功落库逻辑。
|
||||
this.sender.applyCallbackResult(
|
||||
message,
|
||||
SendResult.success(message.getSendTime(), message.getCostTime(), message.getThirdPartyId())
|
||||
);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("电信短信回执查询失败", e);
|
||||
}
|
||||
}, 20, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.njcn.msgpush.module.infra.api.config;
|
||||
package com.njcn.msgpush.module.system.api.config;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.module.infra.enums.ApiConstants;
|
||||
import com.njcn.msgpush.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
@Tag(name = "RPC 服务 - 参数配置")
|
||||
public interface ConfigApi {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.njcn.msgpush.module.system.api.user;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.fhs.core.trans.anno.AutoTrans;
|
||||
import com.fhs.trans.service.AutoTransable;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.util.collection.CollectionUtils;
|
||||
import com.njcn.msgpush.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.njcn.msgpush.module.system.enums.ApiConstants;
|
||||
import com.fhs.core.trans.anno.AutoTrans;
|
||||
import com.fhs.trans.service.AutoTransable;
|
||||
import feign.FeignIgnore;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -22,7 +22,7 @@ import java.util.Map;
|
||||
|
||||
import static com.njcn.msgpush.module.system.api.user.AdminUserApi.PREFIX;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
@Tag(name = "RPC 服务 - 管理员用户")
|
||||
@AutoTrans(namespace = PREFIX, fields = {"nickname"})
|
||||
public interface AdminUserApi extends AutoTransable<AdminUserRespDTO> {
|
||||
@@ -34,11 +34,6 @@ public interface AdminUserApi extends AutoTransable<AdminUserRespDTO> {
|
||||
@Parameter(name = "id", description = "用户编号", example = "1", required = true)
|
||||
CommonResult<AdminUserRespDTO> getUser(@RequestParam("id") Long id);
|
||||
|
||||
@GetMapping(PREFIX + "/list-by-subordinate")
|
||||
@Operation(summary = "通过用户 ID 查询用户下属")
|
||||
@Parameter(name = "id", description = "用户编号", example = "1", required = true)
|
||||
CommonResult<List<AdminUserRespDTO>> getUserListBySubordinate(@RequestParam("id") Long id);
|
||||
|
||||
@GetMapping(PREFIX + "/list")
|
||||
@Operation(summary = "通过用户 ID 查询用户们")
|
||||
@Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
|
||||
@@ -66,9 +61,7 @@ public interface AdminUserApi extends AutoTransable<AdminUserRespDTO> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户是否有效。如下情况,视为无效:
|
||||
* 1. 用户编号不存在
|
||||
* 2. 用户被禁用
|
||||
* 校验用户是否有效
|
||||
*
|
||||
* @param id 用户编号
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.msgpush.module.system.api.websocket;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.util.json.JsonUtils;
|
||||
import com.njcn.msgpush.module.system.api.websocket.dto.WebSocketSendToUsersReqDTO;
|
||||
import com.njcn.msgpush.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
@Tag(name = "RPC 服务 - WebSocket 发送器的") // 对 WebSocketMessageSender 进行封装,提供给其它模块使用
|
||||
public interface WebSocketSenderApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/websocket";
|
||||
|
||||
@PostMapping(PREFIX + "/send-to-users")
|
||||
@Operation(summary = "按用户编号集合发送 WebSocket 消息")
|
||||
CommonResult<Boolean> sendToUsers(@Valid @RequestBody WebSocketSendToUsersReqDTO message);
|
||||
|
||||
/**
|
||||
* 发送消息给指定用户集合
|
||||
*
|
||||
* @param userIds 用户编号集合
|
||||
* @param messageType 消息类型
|
||||
* @param messageContent 消息内容,JSON 格式
|
||||
*/
|
||||
default void send(Collection<Long> userIds, String messageType, String messageContent) {
|
||||
sendToUsers(new WebSocketSendToUsersReqDTO().setUserIds(userIds)
|
||||
.setMessageType(messageType).setMessageContent(messageContent)).checkError();
|
||||
}
|
||||
|
||||
default void sendObject(Collection<Long> userIds, String messageType, Object messageContent) {
|
||||
send(userIds, messageType, JsonUtils.toJsonString(messageContent));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.njcn.msgpush.module.system.api.websocket.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Schema(description = "RPC 服务 - 按用户编号集合发送 WebSocket 消息 Request DTO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WebSocketSendToUsersReqDTO {
|
||||
|
||||
@Schema(description = "用户编号集合", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]")
|
||||
@NotEmpty(message = "用户编号集合不能为空")
|
||||
private Collection<Long> userIds;
|
||||
|
||||
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "notice-push")
|
||||
@NotEmpty(message = "消息类型不能为空")
|
||||
private String messageType;
|
||||
|
||||
@Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"name\":\"李四\"}")
|
||||
@NotEmpty(message = "消息内容不能为空")
|
||||
private String messageContent;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.enums.config;
|
||||
package com.njcn.msgpush.module.system.enums.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.njcn.msgpush.module.system.enums.dept;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 组织节点类型枚举
|
||||
*/
|
||||
public enum DeptOrgTypeEnum {
|
||||
|
||||
COMPANY("company"),
|
||||
DEPT("dept"),
|
||||
DIRECTION("direction"),
|
||||
TEAM("team");
|
||||
|
||||
private final String type;
|
||||
|
||||
DeptOrgTypeEnum(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean isValid(String type) {
|
||||
return Arrays.stream(values()).anyMatch(item -> item.type.equals(type));
|
||||
}
|
||||
|
||||
public static String defaultType() {
|
||||
return DEPT.type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.njcn.msgpush.module.system.enums.dept;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 岗位类型枚举
|
||||
*/
|
||||
public enum PostTypeEnum {
|
||||
|
||||
MANAGEMENT("management"),
|
||||
TECHNICAL("technical"),
|
||||
BUSINESS("business");
|
||||
|
||||
private final String type;
|
||||
|
||||
PostTypeEnum(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean isValid(String type) {
|
||||
return Arrays.stream(values()).anyMatch(item -> item.type.equals(type));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.enums.logger;
|
||||
package com.njcn.msgpush.module.system.enums.logger;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.njcn.msgpush.module.system.enums.permission;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 菜单路由类型枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MenuRouteKindEnum {
|
||||
|
||||
DIR("dir"), // 目录路由
|
||||
VIEW("view"), // 普通页面
|
||||
SINGLE("single"), // 顶级单页
|
||||
IFRAME("iframe"), // iframe 页面
|
||||
EXTERNAL("external"), // 外链页面
|
||||
REDIRECT("redirect"); // 重定向路由
|
||||
|
||||
/**
|
||||
* 路由类型值
|
||||
*/
|
||||
private final String kind;
|
||||
|
||||
public static MenuRouteKindEnum valueOfKind(String kind) {
|
||||
if (StrUtil.isBlank(kind)) {
|
||||
return null;
|
||||
}
|
||||
for (MenuRouteKindEnum value : values()) {
|
||||
if (StrUtil.equalsIgnoreCase(value.getKind(), StrUtil.trim(kind))) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,21 +2,20 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-module-infra</artifactId>
|
||||
<artifactId>msgpush-module-system</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>msgpush-module-infra-server</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
infra 模块,主要提供两块能力:
|
||||
1. 我们放基础设施的运维与管理,支撑上层的通用与核心业务。 例如说:定时任务的管理、服务器的信息等等
|
||||
2. 研发工具,提升研发效率与质量。 例如说:代码生成器、接口文档等等
|
||||
</description>
|
||||
<artifactId>msgpush-module-system-boot</artifactId>
|
||||
<description>系统模块功能服务模块</description>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Cloud 基础 -->
|
||||
@@ -28,31 +27,28 @@
|
||||
<!-- 依赖服务 -->
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-module-infra-api</artifactId>
|
||||
<artifactId>msgpush-system-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-spring-boot-starter-biz-ip</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
@@ -77,6 +73,14 @@
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- websocket 配置中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>msgpush-spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- 消息队列相关 -->
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
@@ -96,15 +100,16 @@
|
||||
<artifactId>msgpush-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 三方云服务相关 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId> <!-- 实现代码生成 -->
|
||||
<groupId>com.anji-plus</groupId>
|
||||
<artifactId>captcha-spring-boot-starter</artifactId> <!-- 验证码,一般用于登录使用 -->
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>de.codecentric</groupId>-->
|
||||
<!-- <artifactId>spring-boot-admin-starter-server</artifactId> <!– 实现 Spring Boot Admin Server 服务端 –>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId> <!-- 文件客户端:文件类型的识别 -->
|
||||
</dependency>
|
||||
|
||||
<!-- 三方云服务相关 -->
|
||||
<dependency>
|
||||
@@ -120,12 +125,8 @@
|
||||
<artifactId>s3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId> <!-- 文件客户端:文件类型的识别 -->
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- 设置构建的 jar 包名 -->
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
@@ -145,5 +146,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -2,7 +2,6 @@ package com.njcn.msgpush.module.system;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
/**
|
||||
* 项目的启动类
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.njcn.msgpush.module.infra.api.config;
|
||||
package com.njcn.msgpush.module.system.api.config;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.module.infra.dal.dataobject.config.ConfigDO;
|
||||
import com.njcn.msgpush.module.infra.service.config.ConfigService;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.config.ConfigDO;
|
||||
import com.njcn.msgpush.module.system.service.config.ConfigService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -11,6 +12,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class ConfigApiImpl implements ConfigApi {
|
||||
|
||||
@Resource
|
||||
@@ -5,6 +5,7 @@ import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.module.system.api.dept.dto.DeptRespDTO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.njcn.msgpush.module.system.service.dept.DeptService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -17,6 +18,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class DeptApiImpl implements DeptApi {
|
||||
|
||||
@Resource
|
||||
@@ -5,6 +5,7 @@ import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.module.system.api.dept.dto.PostRespDTO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.dept.PostDO;
|
||||
import com.njcn.msgpush.module.system.service.dept.PostService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -16,6 +17,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class PostApiImpl implements PostApi {
|
||||
|
||||
@Resource
|
||||
@@ -5,6 +5,7 @@ import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.framework.common.biz.system.dict.dto.DictDataRespDTO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.dict.DictDataDO;
|
||||
import com.njcn.msgpush.module.system.service.dict.DictDataService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -18,6 +19,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Primary // 由于 DictDataCommonApi 的存在,必须声明为 @Primary Bean
|
||||
@Hidden
|
||||
public class DictDataApiImpl implements DictDataApi {
|
||||
|
||||
@Resource
|
||||
@@ -1,18 +1,19 @@
|
||||
package com.njcn.msgpush.module.infra.api.logger;
|
||||
package com.njcn.msgpush.module.system.api.logger;
|
||||
|
||||
import com.njcn.msgpush.framework.common.biz.infra.logger.ApiAccessLogCommonApi;
|
||||
import com.njcn.msgpush.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.biz.system.logger.ApiAccessLogCommonApi;
|
||||
import com.njcn.msgpush.framework.common.biz.system.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.module.infra.service.logger.ApiAccessLogService;
|
||||
import com.njcn.msgpush.module.system.service.logger.ApiAccessLogService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class ApiAccessLogApiImpl implements ApiAccessLogCommonApi {
|
||||
|
||||
@Resource
|
||||
@@ -1,18 +1,19 @@
|
||||
package com.njcn.msgpush.module.infra.api.logger;
|
||||
package com.njcn.msgpush.module.system.api.logger;
|
||||
|
||||
import com.njcn.msgpush.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
|
||||
import com.njcn.msgpush.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.biz.system.logger.ApiErrorLogCommonApi;
|
||||
import com.njcn.msgpush.framework.common.biz.system.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.module.infra.service.logger.ApiErrorLogService;
|
||||
import com.njcn.msgpush.module.system.service.logger.ApiErrorLogService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class ApiErrorLogApiImpl implements ApiErrorLogCommonApi {
|
||||
|
||||
@Resource
|
||||
@@ -8,6 +8,7 @@ import com.njcn.msgpush.module.system.api.logger.dto.OperateLogPageReqDTO;
|
||||
import com.njcn.msgpush.module.system.api.logger.dto.OperateLogRespDTO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.logger.OperateLogDO;
|
||||
import com.njcn.msgpush.module.system.service.logger.OperateLogService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -18,6 +19,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Primary // 由于 OperateLogCommonApi 的存在,必须声明为 @Primary Bean
|
||||
@Hidden
|
||||
public class OperateLogApiImpl implements OperateLogApi {
|
||||
|
||||
@Resource
|
||||
@@ -1,21 +1,23 @@
|
||||
package com.njcn.msgpush.module.system.api.oauth2;
|
||||
|
||||
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
||||
import com.njcn.msgpush.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import com.njcn.msgpush.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import com.njcn.msgpush.module.system.service.oauth2.OAuth2TokenService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@RestController
|
||||
@Validated
|
||||
@Hidden
|
||||
public class OAuth2TokenApiImpl implements OAuth2TokenCommonApi {
|
||||
|
||||
@Resource
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.njcn.msgpush.module.system.api.permission;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
|
||||
import com.njcn.msgpush.module.system.service.permission.PermissionService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -16,6 +16,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Primary // 由于 PermissionCommonApi 的存在,必须声明为 @Primary Bean
|
||||
@Hidden
|
||||
public class PermissionApiImpl implements PermissionApi {
|
||||
|
||||
@Resource
|
||||
@@ -36,9 +37,5 @@ public class PermissionApiImpl implements PermissionApi {
|
||||
return success(permissionService.hasAnyRoles(userId, roles));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<DeptDataPermissionRespDTO> getDeptDataPermission(Long userId) {
|
||||
return success(permissionService.getDeptDataPermission(userId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +1,27 @@
|
||||
package com.njcn.msgpush.module.system.api.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.njcn.msgpush.module.system.service.dept.DeptService;
|
||||
import com.njcn.msgpush.module.system.service.user.AdminUserService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
import static com.njcn.msgpush.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class AdminUserApiImpl implements AdminUserApi {
|
||||
|
||||
@Resource
|
||||
private AdminUserService userService;
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
|
||||
@Override
|
||||
public CommonResult<AdminUserRespDTO> getUser(Long id) {
|
||||
@@ -36,34 +29,6 @@ public class AdminUserApiImpl implements AdminUserApi {
|
||||
return success(BeanUtils.toBean(user, AdminUserRespDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<AdminUserRespDTO>> getUserListBySubordinate(Long id) {
|
||||
// 1.1 获取用户负责的部门
|
||||
AdminUserDO user = userService.getUser(id);
|
||||
if (user == null) {
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
ArrayList<Long> deptIds = new ArrayList<>();
|
||||
DeptDO dept = deptService.getDept(user.getDeptId());
|
||||
if (dept == null) {
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
if (ObjUtil.notEqual(dept.getLeaderUserId(), id)) { // 校验为负责人
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
deptIds.add(dept.getId());
|
||||
// 1.2 获取所有子部门
|
||||
List<DeptDO> childDeptList = deptService.getChildDeptList(dept.getId());
|
||||
if (CollUtil.isNotEmpty(childDeptList)) {
|
||||
deptIds.addAll(convertSet(childDeptList, DeptDO::getId));
|
||||
}
|
||||
|
||||
// 2. 获取部门对应的用户信息
|
||||
List<AdminUserDO> users = userService.getUserListByDeptIds(deptIds);
|
||||
users.removeIf(item -> ObjUtil.equal(item.getId(), id)); // 排除自己
|
||||
return success(BeanUtils.toBean(users, AdminUserRespDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<AdminUserRespDTO>> getUserList(Collection<Long> ids) {
|
||||
List<AdminUserDO> users = userService.getUserList(ids);
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.njcn.msgpush.module.system.api.websocket;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.enums.UserTypeEnum;
|
||||
import com.njcn.msgpush.framework.websocket.core.sender.WebSocketMessageSender;
|
||||
import com.njcn.msgpush.module.system.api.websocket.dto.WebSocketSendToUsersReqDTO;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@Hidden
|
||||
public class WebSocketSenderApiImpl implements WebSocketSenderApi {
|
||||
|
||||
private static final Integer SYSTEM_USER_TYPE = UserTypeEnum.ADMIN.getValue();
|
||||
|
||||
@Resource
|
||||
private WebSocketMessageSender webSocketMessageSender;
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> sendToUsers(WebSocketSendToUsersReqDTO message) {
|
||||
if (CollUtil.isNotEmpty(message.getUserIds())) {
|
||||
message.getUserIds().stream().distinct().forEach(userId ->
|
||||
webSocketMessageSender.send(SYSTEM_USER_TYPE, userId,
|
||||
message.getMessageType(), message.getMessageContent()));
|
||||
}
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,15 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.njcn.msgpush.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.encrypt.core.annotation.ApiEncrypt;
|
||||
import com.njcn.msgpush.framework.security.config.SecurityProperties;
|
||||
import com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.*;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.AuthLoginRespVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.AuthUserRouteRespVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.auth.vo.AuthUserInfoRespVO;
|
||||
import com.njcn.msgpush.module.system.convert.auth.AuthConvert;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.permission.RoleDO;
|
||||
@@ -26,7 +32,12 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
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.Collections;
|
||||
import java.util.List;
|
||||
@@ -53,13 +64,13 @@ public class AuthController {
|
||||
private MenuService menuService;
|
||||
@Resource
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Resource
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@PostMapping("/login")
|
||||
@PermitAll
|
||||
@Operation(summary = "使用账号密码登录")
|
||||
@ApiEncrypt(response = false, requestFields = {"password"})
|
||||
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
||||
return success(authService.login(reqVO));
|
||||
}
|
||||
@@ -84,38 +95,78 @@ public class AuthController {
|
||||
return success(authService.refreshToken(refreshToken));
|
||||
}
|
||||
|
||||
@GetMapping("/get-permission-info")
|
||||
@Operation(summary = "获取登录用户的权限信息")
|
||||
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
|
||||
@GetMapping("/get-user-info")
|
||||
@Operation(summary = "获取登录用户信息")
|
||||
public CommonResult<AuthUserInfoRespVO> getUserInfo() {
|
||||
// 1.1 获得用户信息
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
if (user == null) {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
// 1.2 获得角色列表
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
// 1.2 获得角色和按钮权限
|
||||
List<RoleDO> roles = getCurrentUserRoles();
|
||||
List<MenuDO> menuList = getCurrentUserMenus(roles);
|
||||
return success(AuthConvert.INSTANCE.convertUserInfo(user, roles, menuList));
|
||||
}
|
||||
|
||||
@GetMapping("/get-user-routes")
|
||||
@Operation(summary = "获取登录用户路由信息")
|
||||
public CommonResult<AuthUserRouteRespVO> getUserRoutes() {
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
if (user == null) {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
List<RoleDO> roles = getCurrentUserRoles();
|
||||
List<MenuDO> menuList = getCurrentUserMenus(roles);
|
||||
return success(AuthConvert.INSTANCE.convertUserRoutes(menuList));
|
||||
}
|
||||
|
||||
@GetMapping("/get-permission-info")
|
||||
@Operation(summary = "获取登录用户的权限信息")
|
||||
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
if (user == null) {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
List<RoleDO> roles = getCurrentUserRoles();
|
||||
if (CollUtil.isEmpty(roles)) {
|
||||
return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList()));
|
||||
}
|
||||
List<RoleDO> roles = roleService.getRoleList(roleIds);
|
||||
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
|
||||
|
||||
// 1.3 获得菜单列表
|
||||
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
|
||||
List<MenuDO> menuList = menuService.getMenuList(menuIds);
|
||||
menuList = menuService.filterDisableMenus(menuList);
|
||||
|
||||
// 2. 拼接结果返回
|
||||
List<MenuDO> menuList = getCurrentUserMenus(roles);
|
||||
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
@PermitAll
|
||||
@Operation(summary = "注册用户")
|
||||
@ApiEncrypt(response = false, requestFields = {"password"})
|
||||
public CommonResult<AuthLoginRespVO> register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
|
||||
return success(authService.register(registerReqVO));
|
||||
}
|
||||
|
||||
private List<RoleDO> getCurrentUserRoles() {
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<RoleDO> roles = roleService.getRoleList(roleIds);
|
||||
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus()));
|
||||
return roles;
|
||||
}
|
||||
|
||||
private List<MenuDO> getCurrentUserMenus(List<RoleDO> roles) {
|
||||
if (CollUtil.isEmpty(roles)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
|
||||
List<MenuDO> menuList = menuService.getMenuList(menuIds);
|
||||
return menuService.filterDisableMenus(menuList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.auth.vo;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.njcn.msgpush.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.AssertTrue;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@Schema(description = "管理后台 - 账号密码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数")
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
@Schema(description = "管理后台 - 账号密码登录 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@@ -21,8 +19,8 @@ public class AuthLoginReqVO extends CaptchaVerificationReqVO {
|
||||
|
||||
@Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "msgpushyuanma")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
@Length(min = 4, max = 30, message = "账号长度为 4-30 位")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "账号格式为数字以及字母")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
|
||||
@@ -30,12 +28,4 @@ public class AuthLoginReqVO extends CaptchaVerificationReqVO {
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
// ========== 绑定社交登录时,需要传递如下参数 ==========
|
||||
|
||||
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String socialCode;
|
||||
|
||||
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
private String socialState;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,39 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.auth.vo;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@Schema(description = "管理后台 - Register Request VO")
|
||||
@Schema(description = "管理后台 - 注册 Request VO")
|
||||
@Data
|
||||
public class AuthRegisterReqVO extends CaptchaVerificationReqVO {
|
||||
|
||||
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "msgpush")
|
||||
@NotBlank(message = "用户账号不能为空")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由数字、字母组成")
|
||||
@Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "awen")
|
||||
@NotBlank(message = "用户昵称不能为空")
|
||||
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "所属部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "所属部门不能为空")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(description = "主岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "主岗位不能为空")
|
||||
private Long positionId;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Schema(description = "管理后台 - 用户路由 Meta Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthRouteMetaRespVO {
|
||||
|
||||
@Schema(description = "菜单或页面标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String title;
|
||||
|
||||
@Schema(description = "国际化 key")
|
||||
private String i18nKey;
|
||||
|
||||
@Schema(description = "图标名")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "本地图标名")
|
||||
private String localIcon;
|
||||
|
||||
@Schema(description = "排序值")
|
||||
private Integer order;
|
||||
|
||||
@Schema(description = "是否缓存")
|
||||
private Boolean keepAlive;
|
||||
|
||||
@Schema(description = "是否在菜单中隐藏")
|
||||
private Boolean hideInMenu;
|
||||
|
||||
@Schema(description = "当前页面高亮的菜单路由名")
|
||||
private String activeMenu;
|
||||
|
||||
@Schema(description = "是否支持多标签页")
|
||||
private Boolean multiTab;
|
||||
|
||||
@Schema(description = "标签页固定位置")
|
||||
private Integer fixedIndexInTab;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 用户路由节点 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthRouteNodeRespVO {
|
||||
|
||||
@Schema(description = "路由节点 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "路由名", requiredMode = Schema.RequiredMode.REQUIRED, example = "system_user")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "完整路由路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "/system/user")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "前端组件白名单 key", example = "view.system_user")
|
||||
private String component;
|
||||
|
||||
@Schema(description = "重定向路径")
|
||||
private String redirect;
|
||||
|
||||
@Schema(description = "路由 props")
|
||||
private Object props;
|
||||
|
||||
@Schema(description = "路由 meta", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private AuthRouteMetaRespVO meta;
|
||||
|
||||
@Schema(description = "子路由列表")
|
||||
private List<AuthRouteNodeRespVO> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 登录用户信息 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthUserInfoRespVO {
|
||||
|
||||
@Schema(description = "用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private String userId;
|
||||
|
||||
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "角色编码列表", example = "[\"SUPER_ADMIN\"]")
|
||||
private List<String> roles;
|
||||
|
||||
@Schema(description = "按钮权限码列表", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "[\"system:user:add\", \"system:user:update\"]")
|
||||
private List<String> buttons;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 用户路由 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthUserRouteRespVO {
|
||||
|
||||
@Schema(description = "用户可访问路由树", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<AuthRouteNodeRespVO> routes;
|
||||
|
||||
@Schema(description = "默认首页路由名", requiredMode = Schema.RequiredMode.REQUIRED, example = "system_user")
|
||||
private String home;
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public class CaptchaController {
|
||||
@PostMapping({"/get"})
|
||||
@Operation(summary = "获得验证码")
|
||||
@PermitAll
|
||||
|
||||
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
|
||||
assert request.getRemoteHost() != null;
|
||||
data.setBrowserInfo(getRemoteId(request));
|
||||
@@ -36,6 +37,7 @@ public class CaptchaController {
|
||||
@PostMapping("/check")
|
||||
@Operation(summary = "校验验证码")
|
||||
@PermitAll
|
||||
|
||||
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
|
||||
data.setBrowserInfo(getRemoteId(request));
|
||||
return captchaService.check(data);
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.config;
|
||||
package com.njcn.msgpush.module.system.controller.admin.config;
|
||||
|
||||
import com.njcn.msgpush.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import com.njcn.msgpush.framework.common.pojo.PageResult;
|
||||
import com.njcn.msgpush.framework.excel.core.util.ExcelUtils;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.config.vo.ConfigPageReqVO;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.config.vo.ConfigRespVO;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.config.vo.ConfigSaveReqVO;
|
||||
import com.njcn.msgpush.module.infra.convert.config.ConfigConvert;
|
||||
import com.njcn.msgpush.module.infra.dal.dataobject.config.ConfigDO;
|
||||
import com.njcn.msgpush.module.infra.enums.ErrorCodeConstants;
|
||||
import com.njcn.msgpush.module.infra.service.config.ConfigService;
|
||||
import com.njcn.msgpush.module.system.controller.admin.config.vo.ConfigPageReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.config.vo.ConfigRespVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.config.vo.ConfigSaveReqVO;
|
||||
import com.njcn.msgpush.module.system.convert.config.ConfigConvert;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.config.ConfigDO;
|
||||
import com.njcn.msgpush.module.system.enums.ErrorCodeConstants;
|
||||
import com.njcn.msgpush.module.system.service.config.ConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -31,7 +31,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 参数配置")
|
||||
@RestController
|
||||
@RequestMapping("/infra/config")
|
||||
@RequestMapping("/system/config")
|
||||
@Validated
|
||||
public class ConfigController {
|
||||
|
||||
@@ -40,14 +40,14 @@ public class ConfigController {
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建参数配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:create')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:create')")
|
||||
public CommonResult<Long> createConfig(@Valid @RequestBody ConfigSaveReqVO createReqVO) {
|
||||
return success(configService.createConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改参数配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:update')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:update')")
|
||||
public CommonResult<Boolean> updateConfig(@Valid @RequestBody ConfigSaveReqVO updateReqVO) {
|
||||
configService.updateConfig(updateReqVO);
|
||||
return success(true);
|
||||
@@ -56,7 +56,7 @@ public class ConfigController {
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除参数配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:delete')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:delete')")
|
||||
public CommonResult<Boolean> deleteConfig(@RequestParam("id") Long id) {
|
||||
configService.deleteConfig(id);
|
||||
return success(true);
|
||||
@@ -65,7 +65,7 @@ public class ConfigController {
|
||||
@DeleteMapping("/delete-list")
|
||||
@Operation(summary = "批量删除参数配置")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:delete')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:delete')")
|
||||
public CommonResult<Boolean> deleteConfigList(@RequestParam("ids") List<Long> ids) {
|
||||
configService.deleteConfigList(ids);
|
||||
return success(true);
|
||||
@@ -74,7 +74,7 @@ public class ConfigController {
|
||||
@GetMapping(value = "/get")
|
||||
@Operation(summary = "获得参数配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:query')")
|
||||
public CommonResult<ConfigRespVO> getConfig(@RequestParam("id") Long id) {
|
||||
return success(ConfigConvert.INSTANCE.convert(configService.getConfig(id)));
|
||||
}
|
||||
@@ -95,7 +95,7 @@ public class ConfigController {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获取参数配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:query')")
|
||||
public CommonResult<PageResult<ConfigRespVO>> getConfigPage(@Valid ConfigPageReqVO pageReqVO) {
|
||||
PageResult<ConfigDO> page = configService.getConfigPage(pageReqVO);
|
||||
return success(ConfigConvert.INSTANCE.convertPage(page));
|
||||
@@ -103,7 +103,7 @@ public class ConfigController {
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出参数配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:export')")
|
||||
@PreAuthorize("@ss.hasPermission('system:config:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportConfig(ConfigPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
@@ -115,3 +115,4 @@ public class ConfigController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.config.vo;
|
||||
package com.njcn.msgpush.module.system.controller.admin.config.vo;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.config.vo;
|
||||
package com.njcn.msgpush.module.system.controller.admin.config.vo;
|
||||
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.infra.enums.DictTypeConstants;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.system.enums.DictTypeConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.config.vo;
|
||||
package com.njcn.msgpush.module.system.controller.admin.config.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 参数配置创建/修改 Request VO")
|
||||
@Data
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.dept;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.module.system.controller.admin.dept.vo.orgleader.OrgLeaderRelationRespVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.dept.vo.orgleader.OrgLeaderRelationSaveReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.user.vo.user.UserSimpleRespVO;
|
||||
import com.njcn.msgpush.module.system.convert.user.UserConvert;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.dept.OrgLeaderRelationDO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.njcn.msgpush.module.system.service.dept.DeptService;
|
||||
import com.njcn.msgpush.module.system.service.dept.OrgLeaderRelationService;
|
||||
import com.njcn.msgpush.module.system.service.user.AdminUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
import static com.njcn.msgpush.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - 组织负责人关系")
|
||||
@RestController
|
||||
@RequestMapping("/system/org-leader")
|
||||
@Validated
|
||||
public class OrgLeaderRelationController {
|
||||
|
||||
@Resource
|
||||
private OrgLeaderRelationService orgLeaderRelationService;
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
@Resource
|
||||
private AdminUserService adminUserService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建组织负责人关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:org-leader:create')")
|
||||
public CommonResult<Long> createOrgLeaderRelation(@Valid @RequestBody OrgLeaderRelationSaveReqVO createReqVO) {
|
||||
return success(orgLeaderRelationService.createOrgLeaderRelation(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改组织负责人关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:org-leader:update')")
|
||||
public CommonResult<Boolean> updateOrgLeaderRelation(@Valid @RequestBody OrgLeaderRelationSaveReqVO updateReqVO) {
|
||||
orgLeaderRelationService.updateOrgLeaderRelation(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除组织负责人关系")
|
||||
@Parameter(name = "id", description = "负责人关系编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:org-leader:delete')")
|
||||
public CommonResult<Boolean> deleteOrgLeaderRelation(@RequestParam("id") Long id) {
|
||||
orgLeaderRelationService.deleteOrgLeaderRelation(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/list-by-dept")
|
||||
@Operation(summary = "查询组织下的负责人关系列表")
|
||||
@Parameter(name = "deptId", description = "组织节点 ID", required = true, example = "100")
|
||||
@PreAuthorize("@ss.hasPermission('system:org-leader:query')")
|
||||
public CommonResult<List<OrgLeaderRelationRespVO>> getOrgLeaderRelationListByDept(@RequestParam("deptId") Long deptId) {
|
||||
List<OrgLeaderRelationDO> relations = orgLeaderRelationService.getOrgLeaderRelationListByDeptId(deptId);
|
||||
List<OrgLeaderRelationRespVO> respList = BeanUtils.toBean(relations, OrgLeaderRelationRespVO.class);
|
||||
Map<Long, AdminUserDO> userMap = adminUserService.getUserMap(convertList(relations, OrgLeaderRelationDO::getUserId));
|
||||
respList.forEach(respVO -> {
|
||||
AdminUserDO user = userMap.get(respVO.getUserId());
|
||||
if (user != null) {
|
||||
respVO.setUserNickname(user.getNickname());
|
||||
}
|
||||
});
|
||||
return success(respList);
|
||||
}
|
||||
|
||||
@GetMapping("/candidate-users")
|
||||
@Operation(summary = "查询组织负责人候选用户列表")
|
||||
@Parameter(name = "deptId", description = "组织节点 ID", required = true, example = "100")
|
||||
@PreAuthorize("@ss.hasPermission('system:org-leader:query')")
|
||||
public CommonResult<List<UserSimpleRespVO>> getCandidateUsers(@RequestParam("deptId") Long deptId) {
|
||||
List<AdminUserDO> users = orgLeaderRelationService.getCandidateUsersByDeptId(deptId);
|
||||
Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(users, AdminUserDO::getDeptId));
|
||||
return success(UserConvert.INSTANCE.convertSimpleList(users, deptMap));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,9 @@ public class DeptListReqVO {
|
||||
@Schema(description = "部门名称,模糊匹配", example = "灿能")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "组织节点类型", example = "dept")
|
||||
private String orgType;
|
||||
|
||||
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@@ -12,28 +12,31 @@ public class DeptRespVO {
|
||||
@Schema(description = "部门编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "灿能")
|
||||
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发中心")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父部门 ID", example = "1024")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "组织节点类型", example = "dept")
|
||||
private String orgType;
|
||||
|
||||
@Schema(description = "组织物化路径", example = "/100/101/103/")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "组织层级", example = "3")
|
||||
private Integer level;
|
||||
|
||||
@Schema(description = "组织编码", example = "RD_CENTER")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "负责人的用户编号", example = "2048")
|
||||
private Long leaderUserId;
|
||||
|
||||
@Schema(description = "联系电话", example = "15601691000")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "邮箱", example = "msgpush@iocoder.cn")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.njcn.msgpush.module.system.controller.admin.dept.vo.dept;
|
||||
import com.njcn.msgpush.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.msgpush.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
@@ -16,7 +15,7 @@ public class DeptSaveReqVO {
|
||||
@Schema(description = "部门编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "灿能")
|
||||
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发中心")
|
||||
@NotBlank(message = "部门名称不能为空")
|
||||
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
|
||||
private String name;
|
||||
@@ -24,23 +23,19 @@ public class DeptSaveReqVO {
|
||||
@Schema(description = "父部门 ID", example = "1024")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "组织节点类型", example = "dept")
|
||||
@Size(max = 20, message = "组织节点类型长度不能超过 20 个字符")
|
||||
private String orgType;
|
||||
|
||||
@Schema(description = "组织编码", example = "RD_CENTER")
|
||||
@Size(max = 64, message = "组织编码长度不能超过 64 个字符")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "负责人的用户编号", example = "2048")
|
||||
private Long leaderUserId;
|
||||
|
||||
@Schema(description = "联系电话", example = "15601691000")
|
||||
@Size(max = 11, message = "联系电话长度不能超过11个字符")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "邮箱", example = "msgpush@iocoder.cn")
|
||||
@Email(message = "邮箱格式不正确")
|
||||
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "状态不能为空")
|
||||
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
|
||||
private Integer status;
|
||||
@@ -20,4 +20,7 @@ public class DeptSimpleRespVO {
|
||||
@Schema(description = "父部门 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "组织节点类型", example = "dept")
|
||||
private String orgType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.dept.vo.orgleader;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 组织负责人关系 Response VO")
|
||||
@Data
|
||||
public class OrgLeaderRelationRespVO {
|
||||
|
||||
@Schema(description = "负责人关系编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "组织节点 ID", example = "100")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(description = "负责人用户 ID", example = "1")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "负责人用户昵称", example = "管理员")
|
||||
private String userNickname;
|
||||
|
||||
@Schema(description = "生效开始时间")
|
||||
private LocalDateTime effectiveFrom;
|
||||
|
||||
@Schema(description = "生效结束时间")
|
||||
private LocalDateTime effectiveUntil;
|
||||
|
||||
@Schema(description = "备注", example = "部门负责人")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.dept.vo.orgleader;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 组织负责人关系创建/修改 Request VO")
|
||||
@Data
|
||||
public class OrgLeaderRelationSaveReqVO {
|
||||
|
||||
@Schema(description = "负责人关系编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "组织节点 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
@NotNull(message = "组织节点不能为空")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(description = "负责人用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "负责人用户不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "生效开始时间")
|
||||
private LocalDateTime effectiveFrom;
|
||||
|
||||
@Schema(description = "生效结束时间")
|
||||
private LocalDateTime effectiveUntil;
|
||||
|
||||
@Schema(description = "备注", example = "部门负责人")
|
||||
@Size(max = 500, message = "备注长度不能超过 500 个字符")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -16,6 +16,12 @@ public class PostPageReqVO extends PageParam {
|
||||
@Schema(description = "岗位名称,模糊匹配", example = "灿能")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "岗位类型", example = "technical")
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.njcn.msgpush.module.system.controller.admin.dept.vo.post;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.system.enums.DictTypeConstants;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -19,15 +19,23 @@ public class PostRespVO {
|
||||
@ExcelProperty("岗位序号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
|
||||
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "后端开发工程师")
|
||||
@ExcelProperty("岗位名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "msgpush")
|
||||
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "backend")
|
||||
@ExcelProperty("岗位编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "岗位类型", example = "technical")
|
||||
@ExcelProperty("岗位类型")
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
@ExcelProperty("岗位级别")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("岗位排序")
|
||||
private Integer sort;
|
||||
|
||||
@@ -36,7 +44,7 @@ public class PostRespVO {
|
||||
@DictFormat(DictTypeConstants.COMMON_STATUS)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "备注", example = "快乐的备注")
|
||||
@Schema(description = "备注", example = "技术序列岗位")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@@ -3,6 +3,7 @@ package com.njcn.msgpush.module.system.controller.admin.dept.vo.post;
|
||||
import com.njcn.msgpush.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.msgpush.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
@@ -15,17 +16,25 @@ public class PostSaveReqVO {
|
||||
@Schema(description = "岗位编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
|
||||
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "后端开发工程师")
|
||||
@NotBlank(message = "岗位名称不能为空")
|
||||
@Size(max = 50, message = "岗位名称长度不能超过 50 个字符")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "msgpush")
|
||||
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "backend")
|
||||
@NotBlank(message = "岗位编码不能为空")
|
||||
@Size(max = 64, message = "岗位编码长度不能超过64个字符")
|
||||
@Size(max = 64, message = "岗位编码长度不能超过 64 个字符")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "岗位类型", example = "technical")
|
||||
@Size(max = 20, message = "岗位类型长度不能超过 20 个字符")
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
@Min(value = 0, message = "岗位级别不能小于 0")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
private Integer sort;
|
||||
|
||||
@@ -33,7 +42,7 @@ public class PostSaveReqVO {
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "备注", example = "快乐的备注")
|
||||
@Schema(description = "备注", example = "技术序列岗位")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -16,4 +16,16 @@ public class PostSimpleRespVO {
|
||||
@ExcelProperty("岗位名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "岗位编码", example = "backend")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "岗位类型", example = "technical")
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "岗位排序", example = "1")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
@@ -75,6 +75,7 @@ public class DictTypeController {
|
||||
@Operation(summary = "获得字典类型的分页列表")
|
||||
@PreAuthorize("@ss.hasPermission('system:dict:query')")
|
||||
public CommonResult<PageResult<DictTypeRespVO>> pageDictTypes(@Valid DictTypePageReqVO pageReqVO) {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
PageResult<DictTypeDO> pageResult = dictTypeService.getDictTypePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, DictTypeRespVO.class));
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -23,6 +24,10 @@ public class DictTypePageReqVO extends PageParam {
|
||||
@Size(max = 100, message = "字典类型类型长度不能超过100个字符")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "字典类型编码,兼容前端 code 查询参数", example = "sys_common_sex")
|
||||
@Size(max = 100, message = "字典类型编码长度不能超过100个字符")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@@ -30,4 +35,8 @@ public class DictTypePageReqVO extends PageParam {
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
public String getTypeKeyword() {
|
||||
return StringUtils.hasText(code) ? code : type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.pojo.PageResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.file.vo.config.FileConfigRespVO;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO;
|
||||
import com.njcn.msgpush.module.infra.dal.dataobject.file.FileConfigDO;
|
||||
import com.njcn.msgpush.module.infra.service.file.FileConfigService;
|
||||
import com.njcn.msgpush.module.system.controller.admin.file.vo.config.FileConfigPageReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.file.vo.config.FileConfigRespVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.file.vo.config.FileConfigSaveReqVO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.file.FileConfigDO;
|
||||
import com.njcn.msgpush.module.system.service.file.FileConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -23,7 +23,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 文件配置")
|
||||
@RestController
|
||||
@RequestMapping("/infra/file-config")
|
||||
@RequestMapping("/system/file-config")
|
||||
@Validated
|
||||
public class FileConfigController {
|
||||
|
||||
@@ -32,14 +32,14 @@ public class FileConfigController {
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建文件配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:create')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:create')")
|
||||
public CommonResult<Long> createFileConfig(@Valid @RequestBody FileConfigSaveReqVO createReqVO) {
|
||||
return success(fileConfigService.createFileConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新文件配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:update')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:update')")
|
||||
public CommonResult<Boolean> updateFileConfig(@Valid @RequestBody FileConfigSaveReqVO updateReqVO) {
|
||||
fileConfigService.updateFileConfig(updateReqVO);
|
||||
return success(true);
|
||||
@@ -47,7 +47,7 @@ public class FileConfigController {
|
||||
|
||||
@PutMapping("/update-master")
|
||||
@Operation(summary = "更新文件配置为 Master")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:update')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:update')")
|
||||
public CommonResult<Boolean> updateFileConfigMaster(@RequestParam("id") Long id) {
|
||||
fileConfigService.updateFileConfigMaster(id);
|
||||
return success(true);
|
||||
@@ -56,7 +56,7 @@ public class FileConfigController {
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除文件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:delete')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:delete')")
|
||||
public CommonResult<Boolean> deleteFileConfig(@RequestParam("id") Long id) {
|
||||
fileConfigService.deleteFileConfig(id);
|
||||
return success(true);
|
||||
@@ -65,7 +65,7 @@ public class FileConfigController {
|
||||
@DeleteMapping("/delete-list")
|
||||
@Operation(summary = "批量删除文件配置")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:delete')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:delete')")
|
||||
public CommonResult<Boolean> deleteFileConfigList(@RequestParam("ids") List<Long> ids) {
|
||||
fileConfigService.deleteFileConfigList(ids);
|
||||
return success(true);
|
||||
@@ -74,7 +74,7 @@ public class FileConfigController {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得文件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:query')")
|
||||
public CommonResult<FileConfigRespVO> getFileConfig(@RequestParam("id") Long id) {
|
||||
FileConfigDO config = fileConfigService.getFileConfig(id);
|
||||
return success(BeanUtils.toBean(config, FileConfigRespVO.class));
|
||||
@@ -82,7 +82,7 @@ public class FileConfigController {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得文件配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:query')")
|
||||
public CommonResult<PageResult<FileConfigRespVO>> getFileConfigPage(@Valid FileConfigPageReqVO pageVO) {
|
||||
PageResult<FileConfigDO> pageResult = fileConfigService.getFileConfigPage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, FileConfigRespVO.class));
|
||||
@@ -90,9 +90,10 @@ public class FileConfigController {
|
||||
|
||||
@GetMapping("/test")
|
||||
@Operation(summary = "测试文件配置是否正确")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file-config:query')")
|
||||
public CommonResult<String> testFileConfig(@RequestParam("id") Long id) throws Exception {
|
||||
String url = fileConfigService.testFileConfig(id);
|
||||
return success(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@@ -6,10 +6,9 @@ import cn.hutool.core.util.URLUtil;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
import com.njcn.msgpush.framework.common.pojo.PageResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
|
||||
import com.njcn.msgpush.module.infra.controller.admin.file.vo.file.*;
|
||||
import com.njcn.msgpush.module.infra.dal.dataobject.file.FileDO;
|
||||
import com.njcn.msgpush.module.infra.service.file.FileService;
|
||||
import com.njcn.msgpush.module.system.controller.admin.file.vo.file.*;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.file.FileDO;
|
||||
import com.njcn.msgpush.module.system.service.file.FileService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
@@ -31,11 +30,11 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
import static com.njcn.msgpush.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
||||
import static com.njcn.msgpush.module.system.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
||||
|
||||
@Tag(name = "管理后台 - 文件存储")
|
||||
@RestController
|
||||
@RequestMapping("/infra/file")
|
||||
@RequestMapping("/system/file")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class FileController {
|
||||
@@ -75,7 +74,7 @@ public class FileController {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得文件")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file:query')")
|
||||
public CommonResult<FileRespVO> getFile(@RequestParam("id") Long id) {
|
||||
return success(BeanUtils.toBean(fileService.getFile(id), FileRespVO.class));
|
||||
}
|
||||
@@ -83,7 +82,7 @@ public class FileController {
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除文件")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file:delete')")
|
||||
public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) throws Exception {
|
||||
fileService.deleteFile(id);
|
||||
return success(true);
|
||||
@@ -92,7 +91,7 @@ public class FileController {
|
||||
@DeleteMapping("/delete-list")
|
||||
@Operation(summary = "批量删除文件")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file:delete')")
|
||||
public CommonResult<Boolean> deleteFileList(@RequestParam("ids") List<Long> ids) throws Exception {
|
||||
fileService.deleteFileList(ids);
|
||||
return success(true);
|
||||
@@ -100,6 +99,7 @@ public class FileController {
|
||||
|
||||
@GetMapping("/{configId}/get/**")
|
||||
@PermitAll
|
||||
|
||||
@Operation(summary = "下载文件")
|
||||
@Parameter(name = "configId", description = "配置编号", required = true)
|
||||
public void getFileContent(HttpServletRequest request,
|
||||
@@ -127,10 +127,11 @@ public class FileController {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得文件分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:file:query')")
|
||||
public CommonResult<PageResult<FileRespVO>> getFilePage(@Valid FilePageReqVO pageVO) {
|
||||
PageResult<FileDO> pageResult = fileService.getFilePage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, FileRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.config;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.config;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.config;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.config;
|
||||
|
||||
import com.njcn.msgpush.module.infra.framework.file.core.client.FileClientConfig;
|
||||
import com.njcn.msgpush.module.system.framework.file.core.client.FileClientConfig;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.config;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - 文件配置创建/修改 Request VO")
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@@ -28,6 +28,6 @@ public class FileCreateReqVO {
|
||||
private String type;
|
||||
|
||||
@Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer size;
|
||||
private Long size;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.file;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
@@ -28,7 +28,7 @@ public class FileRespVO {
|
||||
private String type;
|
||||
|
||||
@Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer size;
|
||||
private Long size;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.file.vo.file;
|
||||
package com.njcn.msgpush.module.system.controller.admin.file.vo.file;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.logger;
|
||||
package com.njcn.msgpush.module.system.controller.admin.logger;
|
||||
|
||||
import com.njcn.msgpush.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
@@ -6,10 +6,10 @@ import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import com.njcn.msgpush.framework.common.pojo.PageResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.framework.excel.core.util.ExcelUtils;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO;
|
||||
import com.njcn.msgpush.module.infra.dal.dataobject.logger.ApiAccessLogDO;
|
||||
import com.njcn.msgpush.module.infra.service.logger.ApiAccessLogService;
|
||||
import com.njcn.msgpush.module.system.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.logger.ApiAccessLogDO;
|
||||
import com.njcn.msgpush.module.system.service.logger.ApiAccessLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -31,7 +31,7 @@ import static com.njcn.msgpush.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - API 访问日志")
|
||||
@RestController
|
||||
@RequestMapping("/infra/api-access-log")
|
||||
@RequestMapping("/system/api-access-log")
|
||||
@Validated
|
||||
public class ApiAccessLogController {
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ApiAccessLogController {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得 API 访问日志")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-access-log:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-access-log:query')")
|
||||
public CommonResult<ApiAccessLogRespVO> getApiAccessLog(@RequestParam("id") Long id) {
|
||||
ApiAccessLogDO apiAccessLog = apiAccessLogService.getApiAccessLog(id);
|
||||
return success(BeanUtils.toBean(apiAccessLog, ApiAccessLogRespVO.class));
|
||||
@@ -49,7 +49,7 @@ public class ApiAccessLogController {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得API 访问日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-access-log:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-access-log:query')")
|
||||
public CommonResult<PageResult<ApiAccessLogRespVO>> getApiAccessLogPage(@Valid ApiAccessLogPageReqVO pageReqVO) {
|
||||
PageResult<ApiAccessLogDO> pageResult = apiAccessLogService.getApiAccessLogPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, ApiAccessLogRespVO.class));
|
||||
@@ -57,7 +57,7 @@ public class ApiAccessLogController {
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出API 访问日志 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-access-log:export')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-access-log:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportApiAccessLogExcel(@Valid ApiAccessLogPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
@@ -69,3 +69,4 @@ public class ApiAccessLogController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.logger;
|
||||
package com.njcn.msgpush.module.system.controller.admin.logger;
|
||||
|
||||
import com.njcn.msgpush.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import com.njcn.msgpush.framework.common.pojo.CommonResult;
|
||||
@@ -6,10 +6,10 @@ import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import com.njcn.msgpush.framework.common.pojo.PageResult;
|
||||
import com.njcn.msgpush.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.msgpush.framework.excel.core.util.ExcelUtils;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO;
|
||||
import com.njcn.msgpush.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO;
|
||||
import com.njcn.msgpush.module.infra.dal.dataobject.logger.ApiErrorLogDO;
|
||||
import com.njcn.msgpush.module.infra.service.logger.ApiErrorLogService;
|
||||
import com.njcn.msgpush.module.system.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO;
|
||||
import com.njcn.msgpush.module.system.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO;
|
||||
import com.njcn.msgpush.module.system.dal.dataobject.logger.ApiErrorLogDO;
|
||||
import com.njcn.msgpush.module.system.service.logger.ApiErrorLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
@@ -30,7 +30,7 @@ import static com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUti
|
||||
|
||||
@Tag(name = "管理后台 - API 错误日志")
|
||||
@RestController
|
||||
@RequestMapping("/infra/api-error-log")
|
||||
@RequestMapping("/system/api-error-log")
|
||||
@Validated
|
||||
public class ApiErrorLogController {
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ApiErrorLogController {
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024"),
|
||||
@Parameter(name = "processStatus", description = "处理状态", required = true, example = "1")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:update-status')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-error-log:update-status')")
|
||||
public CommonResult<Boolean> updateApiErrorLogProcess(@RequestParam("id") Long id,
|
||||
@RequestParam("processStatus") Integer processStatus) {
|
||||
apiErrorLogService.updateApiErrorLogProcess(id, processStatus, getLoginUserId());
|
||||
@@ -53,7 +53,7 @@ public class ApiErrorLogController {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得 API 错误日志")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-error-log:query')")
|
||||
public CommonResult<ApiErrorLogRespVO> getApiErrorLog(@RequestParam("id") Long id) {
|
||||
ApiErrorLogDO apiErrorLog = apiErrorLogService.getApiErrorLog(id);
|
||||
return success(BeanUtils.toBean(apiErrorLog, ApiErrorLogRespVO.class));
|
||||
@@ -61,7 +61,7 @@ public class ApiErrorLogController {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得 API 错误日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:query')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-error-log:query')")
|
||||
public CommonResult<PageResult<ApiErrorLogRespVO>> getApiErrorLogPage(@Valid ApiErrorLogPageReqVO pageReqVO) {
|
||||
PageResult<ApiErrorLogDO> pageResult = apiErrorLogService.getApiErrorLogPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, ApiErrorLogRespVO.class));
|
||||
@@ -69,7 +69,7 @@ public class ApiErrorLogController {
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出 API 错误日志 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:export')")
|
||||
@PreAuthorize("@ss.hasPermission('system:api-error-log:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportApiErrorLogExcel(@Valid ApiErrorLogPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
@@ -81,3 +81,4 @@ public class ApiErrorLogController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.logger.vo.apiaccesslog;
|
||||
package com.njcn.msgpush.module.system.controller.admin.logger.vo.apiaccesslog;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.logger.vo.apiaccesslog;
|
||||
package com.njcn.msgpush.module.system.controller.admin.logger.vo.apiaccesslog;
|
||||
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.infra.enums.DictTypeConstants;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.system.enums.DictTypeConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -70,7 +70,7 @@ public class ApiAccessLogRespVO {
|
||||
|
||||
@Schema(description = "操作分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "操作分类", converter = DictConvert.class)
|
||||
@DictFormat(com.njcn.msgpush.module.infra.enums.DictTypeConstants.OPERATE_TYPE)
|
||||
@DictFormat(DictTypeConstants.OPERATE_TYPE)
|
||||
private Integer operateType;
|
||||
|
||||
@Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@@ -89,7 +89,7 @@ public class ApiAccessLogRespVO {
|
||||
@ExcelProperty("结果码")
|
||||
private Integer resultCode;
|
||||
|
||||
@Schema(description = "结果提示", example = "灿能源码,牛逼!")
|
||||
@Schema(description = "结果提示", example = "灿能,牛逼!")
|
||||
@ExcelProperty("结果提示")
|
||||
private String resultMsg;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.logger.vo.apierrorlog;
|
||||
package com.njcn.msgpush.module.system.controller.admin.logger.vo.apierrorlog;
|
||||
|
||||
import com.njcn.msgpush.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.njcn.msgpush.module.infra.controller.admin.logger.vo.apierrorlog;
|
||||
package com.njcn.msgpush.module.system.controller.admin.logger.vo.apierrorlog;
|
||||
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.infra.enums.DictTypeConstants;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.njcn.msgpush.framework.excel.core.annotations.DictFormat;
|
||||
import com.njcn.msgpush.framework.excel.core.convert.DictConvert;
|
||||
import com.njcn.msgpush.module.system.enums.DictTypeConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class OperateLogRespVO implements VO {
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userName")
|
||||
private Long userId;
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "awen")
|
||||
@ExcelProperty("操作人")
|
||||
private String userName;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user