feat: 新增短信配置 (#144)

This commit is contained in:
luoqiz
2025-03-17 14:35:17 +08:00
committed by GitHub
parent 1044b68eb8
commit 1a4716f3ba
36 changed files with 1957 additions and 2 deletions

View File

@@ -54,6 +54,12 @@
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- postgresql Java 驱动 -->
<!-- <dependency>-->
<!-- <groupId>org.postgresql</groupId>-->
<!-- <artifactId>postgresql</artifactId>-->
<!-- </dependency>-->
<!-- ContiNew Starter 扩展模块 - CURD增删改查 -->
<dependency>
<groupId>top.continew</groupId>

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.common.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.continew.starter.core.enums.BaseEnum;
/**
* 方法类型枚举
*
* @author luoqiz
* @since 2025/03/16 13:38
*/
@Getter
@RequiredArgsConstructor
public enum MethodTypeEnum implements BaseEnum<String> {
/**
* 新增
*/
ADD("add", "新增"),
/**
* 更新
*/
UPDATE("update", "更新"),
/**
* 删除
*/
DELETE("delete", "删除"),
/**
* 删除
*/
SEARCH("search", "查询"),;
private final String value;
private final String description;
}

View File

@@ -18,5 +18,12 @@
<groupId>top.continew</groupId>
<artifactId>continew-common</artifactId>
</dependency>
<dependency>
<groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-spring-boot-starter</artifactId>
<version>3.3.4</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.core.proxy.SmsProxyFactory;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SmsBlendConfig {
@Resource
SmsJdbcReadConfig config;
@Resource
private SmsRecordProcessor smsRecordProcessor;
@EventListener
public void init(ContextRefreshedEvent event) {
log.info("初始化短信配置");
// 创建SmsBlend 短信实例
SmsFactory.createSmsBlend(config);
SmsProxyFactory.addPreProcessor(smsRecordProcessor);
log.info("初始化短信配置完成");
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms;
import jakarta.annotation.Resource;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.provider.config.BaseConfig;
import org.springframework.stereotype.Component;
import top.continew.admin.system.config.sms.utils.SmsConvertUtils;
import top.continew.admin.system.model.query.SmsConfigQuery;
import top.continew.admin.system.model.resp.SmsConfigDetailResp;
import top.continew.admin.system.model.resp.SmsConfigResp;
import top.continew.admin.system.service.SmsConfigService;
import top.continew.starter.extension.crud.model.query.SortQuery;
import java.util.ArrayList;
import java.util.List;
@Component
public class SmsJdbcReadConfig implements SmsReadConfig {
@Resource
private SmsConfigService smsConfigService;
@Override
public BaseConfig getSupplierConfig(String configId) {
Long id = Long.parseLong(configId);
SmsConfigDetailResp smsConfig = smsConfigService.get(id);
if (smsConfig == null || !smsConfig.getIsEnable()) {
return null;
}
return SmsConvertUtils.smsConfig2BaseConfig(smsConfig);
}
@Override
public List<BaseConfig> getSupplierConfigList() {
SmsConfigQuery smsConfigQuery = new SmsConfigQuery();
smsConfigQuery.setIsEnable(true);
SortQuery sortQuery = new SortQuery();
sortQuery.setSort(new String[] {"id", "desc"});
List<SmsConfigResp> smsConfigList = smsConfigService.list(smsConfigQuery, sortQuery);
List<BaseConfig> baseConfigList = new ArrayList<>();
for (SmsConfigResp smsConfigResp : smsConfigList) {
baseConfigList.add(SmsConvertUtils.smsConfig2BaseConfig(smsConfigResp));
}
return baseConfigList;
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.api.proxy.CoreMethodProcessor;
import org.springframework.stereotype.Component;
import top.continew.admin.system.model.req.SmsRecordReq;
import top.continew.admin.system.service.SmsRecordService;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
@Slf4j
@Component
public class SmsRecordProcessor implements CoreMethodProcessor {
@Resource
private SmsRecordService smsRecordService;
@Override
public Object[] preProcessor(Method method, Object source, Object[] param) {
return CoreMethodProcessor.super.preProcessor(method, source, param);
}
@Override
public void sendMessagePreProcess(String phone, Object message) {
System.out.println("发送短信前处理" + phone + message);
}
@Override
public void sendMessageByTemplatePreProcess(String phone,
String templateId,
LinkedHashMap<String, String> messages) {
log.debug("发送短信前处理 sendMessageByTemplatePreProcess " + phone + templateId + JSONUtil.toJsonPrettyStr(messages));
}
@Override
public void massTextingPreProcess(List<String> phones, String message) {
log.debug("发送短信前处理 massTextingPreProcess " + JSONUtil.toJsonPrettyStr(phones) + message);
}
@Override
public void massTextingByTemplatePreProcess(List<String> phones,
String templateId,
LinkedHashMap<String, String> messages) {
log.debug("发送短信前处理 massTextingByTemplatePreProcess " + JSONUtil.toJsonPrettyStr(phones) + JSONUtil
.toJsonPrettyStr(messages));
}
@Override
public Object postProcessor(SmsResponse result, Object[] param) {
SmsRecordReq record = new SmsRecordReq();
record.setConfigId(Long.parseLong(result.getConfigId()));
record.setPhone(param[0].toString());
record.setParams(JSONUtil.toJsonPrettyStr(param[1]));
record.setStatus(result.isSuccess());
record.setResMsg(JSONUtil.toJsonPrettyStr(result.getData()));
smsRecordService.add(record);
return CoreMethodProcessor.super.postProcessor(result, param);
}
@Override
public void exceptionHandleProcessor(Method method,
Object source,
Object[] param,
Exception exception) throws RuntimeException {
CoreMethodProcessor.super.exceptionHandleProcessor(method, source, param, exception);
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms.event;
import lombok.Data;
import top.continew.admin.common.enums.MethodTypeEnum;
import java.io.Serializable;
@Data
public class SmsEventMessage implements Serializable {
private static final long serialVersionUID = 1L;
private final MethodTypeEnum type;
private final String configId;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms.event;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
@Configuration
public class SmsRedisConfig {
public static final String SysSmsChannel = "system:sms:topic";
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new ChannelTopic(SysSmsChannel));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(SmsRedisMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms.event;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SmsRedisMessagePublisher {
@Resource
private RedisTemplate redisTemplate;
public void publish(String channel, SmsEventMessage message) {
redisTemplate.convertAndSend(channel, message);
log.debug("Message published to Redis channel [" + channel + "]: " + message);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms.event;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.provider.config.BaseConfig;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import top.continew.admin.system.config.sms.SmsJdbcReadConfig;
@Slf4j
@Component
public class SmsRedisMessageSubscriber implements MessageListener {
@Resource
private RedisTemplate redisTemplate;
@Resource
private SmsJdbcReadConfig smsJdbcReadConfig;
@Override
public void onMessage(Message message, byte[] pattern) {
byte[] body = message.getBody();
SmsEventMessage msg = (SmsEventMessage)redisTemplate.getValueSerializer().deserialize(body);
switch (msg.getType()) {
case ADD:
BaseConfig config = smsJdbcReadConfig.getSupplierConfig(msg.getConfigId());
if (config != null) {
SmsFactory.createSmsBlend(config);
}
break;
case UPDATE:
BaseConfig updateConfig = smsJdbcReadConfig.getSupplierConfig(msg.getConfigId());
// 若是存在该配置,则先删除
if (SmsFactory.getSmsBlend(msg.getConfigId()) != null) {
SmsFactory.unregister(msg.getConfigId());
}
if (updateConfig != null) {
SmsFactory.createSmsBlend(updateConfig);
}
break;
case DELETE:
SmsFactory.unregister(msg.getConfigId());
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.config.sms.utils;
import org.dromara.sms4j.aliyun.config.AlibabaConfig;
import org.dromara.sms4j.cloopen.config.CloopenConfig;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.ctyun.config.CtyunConfig;
import org.dromara.sms4j.provider.config.BaseConfig;
import top.continew.admin.system.model.resp.SmsConfigDetailResp;
import top.continew.admin.system.model.resp.SmsConfigResp;
public class SmsConvertUtils {
public static BaseConfig smsConfig2BaseConfig(SmsConfigResp smsConfig) {
switch (smsConfig.getSupplier()) {
case SupplierConstant.ALIBABA: {
AlibabaConfig alibabaConfig = new AlibabaConfig();
alibabaConfig.setConfigId(smsConfig.getId().toString());
alibabaConfig.setAccessKeyId(smsConfig.getAccessKeyId());
alibabaConfig.setAccessKeySecret(smsConfig.getAccessKeySecret());
alibabaConfig.setSignature(smsConfig.getSignature());
alibabaConfig.setTemplateId(smsConfig.getTemplateId());
return alibabaConfig;
}
case SupplierConstant.CLOOPEN: {
CloopenConfig config = new CloopenConfig();
config.setConfigId(smsConfig.getId().toString());
config.setAccessKeyId(smsConfig.getAccessKeyId());
config.setAccessKeySecret(smsConfig.getAccessKeySecret());
config.setSignature(smsConfig.getSignature());
config.setTemplateId(smsConfig.getTemplateId());
return config;
}
case SupplierConstant.CTYUN: {
CtyunConfig config = new CtyunConfig();
config.setConfigId(smsConfig.getId().toString());
config.setAccessKeyId(smsConfig.getAccessKeyId());
config.setAccessKeySecret(smsConfig.getAccessKeySecret());
config.setSignature(smsConfig.getSignature());
config.setTemplateId(smsConfig.getTemplateId());
return config;
}
}
throw new RuntimeException("短信配置有错误,未知的供应商");
}
public static BaseConfig smsConfig2BaseConfig(SmsConfigDetailResp smsConfig) {
switch (smsConfig.getSupplier()) {
case SupplierConstant.ALIBABA: {
AlibabaConfig alibabaConfig = new AlibabaConfig();
alibabaConfig.setConfigId(smsConfig.getId().toString());
alibabaConfig.setAccessKeyId(smsConfig.getAccessKeyId());
alibabaConfig.setAccessKeySecret(smsConfig.getAccessKeySecret());
alibabaConfig.setSignature(smsConfig.getSignature());
alibabaConfig.setTemplateId(smsConfig.getTemplateId());
return alibabaConfig;
}
case SupplierConstant.CLOOPEN: {
CloopenConfig config = new CloopenConfig();
config.setConfigId(smsConfig.getId().toString());
config.setAccessKeyId(smsConfig.getAccessKeyId());
config.setAccessKeySecret(smsConfig.getAccessKeySecret());
config.setSignature(smsConfig.getSignature());
config.setTemplateId(smsConfig.getTemplateId());
return config;
}
case SupplierConstant.CTYUN: {
CtyunConfig config = new CtyunConfig();
config.setConfigId(smsConfig.getId().toString());
config.setAccessKeyId(smsConfig.getAccessKeyId());
config.setAccessKeySecret(smsConfig.getAccessKeySecret());
config.setSignature(smsConfig.getSignature());
config.setTemplateId(smsConfig.getTemplateId());
return config;
}
}
throw new RuntimeException("短信配置有错误,未知的供应商");
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import top.continew.starter.core.enums.BaseEnum;
/**
* 菜单类型枚举
*
* @author Charles7c
* @since 2023/2/15 20:12
*/
@Getter
@RequiredArgsConstructor
public enum SmsSupplierEnum implements BaseEnum<String> {
ALIBABA(SupplierConstant.ALIBABA, "阿里云"), CLOOPEN(SupplierConstant.CLOOPEN, "容联云"),
CTYUN(SupplierConstant.CTYUN, "天翼云"),
// EMAY(SupplierConstant.EMAY, "亿美软通"), HUAWEI(SupplierConstant.HUAWEI, "华为云短信"),
// JDCLOUD(SupplierConstant.JDCLOUD, "京东云短信"), NETEASE(SupplierConstant.NETEASE, "网易云信"),
// TENCENT(SupplierConstant.TENCENT, "腾讯云短信"), UNISMS(SupplierConstant.UNISMS, "合一短信"),
// YUNPIAN(SupplierConstant.YUNPIAN, "云片短信"), ZHUTONG(SupplierConstant.ZHUTONG, "助通短信"),
// LIANLU(SupplierConstant.LIANLU, "联麓短信"), DINGZHONG(SupplierConstant.DINGZHONG, "鼎众短信"),
// QINIU(SupplierConstant.QINIU, "七牛云短信"), CHUANGLAN(SupplierConstant.CHUANGLAN, "创蓝短信"),
// JIGUANG(SupplierConstant.JIGUANG, "极光短信"), BUDING_V2(SupplierConstant.BUDING_V2, "布丁云V2"),
// MAS(SupplierConstant.MAS, "中国移动 云MAS"), BAIDU(SupplierConstant.BAIDU, "百度云短信"),
// LUO_SI_MAO(SupplierConstant.LUO_SI_MAO, "螺丝帽短信"), MY_SUBMAIL(SupplierConstant.MY_SUBMAIL, "SUBMAIL短信"),
// DAN_MI(SupplierConstant.DAN_MI, "单米短信"), YIXINTONG(SupplierConstant.YIXINTONG, "亿信通"),
;
private final String value;
private final String description;
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.mapper;
import top.continew.starter.data.mp.base.BaseMapper;
import top.continew.admin.system.model.entity.SmsConfigDO;
/**
* 短信服务配置 Mapper
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
public interface SmsConfigMapper extends BaseMapper<SmsConfigDO> {}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.mapper;
import top.continew.starter.data.mp.base.BaseMapper;
import top.continew.admin.system.model.entity.SmsRecordDO;
/**
* 短信记录 Mapper
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
public interface SmsRecordMapper extends BaseMapper<SmsRecordDO> {}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import top.continew.admin.common.model.entity.BaseDO;
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
import java.io.Serial;
/**
* 短信服务配置实体
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Data
@TableName("sys_sms_config")
public class SmsConfigDO extends BaseDO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
private String name;
/**
* 厂商名称标识
*/
private String supplier;
/**
* Access Key 或 API Key
*/
private String accessKeyId;
/**
* Access Secret 或 API Secret
*/
@FieldEncrypt
private String accessKeySecret;
/**
* 短信签名
*/
private String signature;
/**
* 模板 ID
*/
private String templateId;
/**
* 负载均衡权重
*/
private Integer weight;
/**
* 短信自动重试间隔时间(秒)
*/
private Integer retryInterval;
/**
* 短信重试次数
*/
private Integer maxRetries;
/**
* 当前厂商的发送数量上限
*/
private Integer maximum;
/**
* 各个厂商独立配置
*/
private String supplierConfig;
/**
* 是否启用
*/
private Boolean isEnable;
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.entity;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableName;
import top.continew.admin.common.model.entity.BaseDO;
import java.io.Serial;
/**
* 短信记录实体
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Data
@TableName("sys_sms_record")
public class SmsRecordDO extends BaseDO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置id
*/
private Long configId;
/**
* 手机号
*/
private String phone;
/**
* 参数配置
*/
private String params;
/**
* 发送状态
*/
private Boolean status;
/**
* 返回数据
*/
private String resMsg;
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.enums.QueryType;
import java.io.Serial;
import java.io.Serializable;
/**
* 短信服务配置查询条件
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Data
@Schema(description = "短信服务配置查询条件")
public class SmsConfigQuery implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Schema(description = "名称")
@Query(type = QueryType.LIKE)
private String name;
/**
* 厂商名称标识
*/
@Schema(description = "厂商名称标识")
@Query(type = QueryType.EQ)
private String supplier;
/**
* Access Key 或 API Key
*/
@Schema(description = "Access Key 或 API Key")
@Query(type = QueryType.EQ)
private String accessKeyId;
/**
* 短信签名
*/
@Schema(description = "短信签名")
@Query(type = QueryType.EQ)
private String signature;
/**
* 模板 ID
*/
@Schema(description = "模板 ID")
@Query(type = QueryType.EQ)
private String templateId;
/**
* 是否启用
*/
@Schema(description = "是否启用")
@Query(type = QueryType.EQ)
private Boolean isEnable;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.enums.QueryType;
import java.io.Serial;
import java.io.Serializable;
/**
* 短信记录查询条件
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Data
@Schema(description = "短信记录查询条件")
public class SmsRecordQuery implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置id
*/
@Schema(description = "配置id")
@Query(type = QueryType.EQ)
private Long configId;
/**
* 手机号
*/
@Schema(description = "手机号")
@Query(type = QueryType.EQ)
private String phone;
/**
* 发送状态
*/
@Schema(description = "发送状态")
@Query(type = QueryType.EQ)
private Boolean status;
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.req;
import jakarta.validation.constraints.*;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import org.hibernate.validator.constraints.Length;
import java.io.Serial;
import java.io.Serializable;
/**
* 创建或修改短信服务配置参数
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Data
@Schema(description = "创建或修改短信服务配置参数")
public class SmsConfigReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Schema(description = "名称")
@NotBlank(message = "名称不能为空")
@Length(max = 255, message = "名称长度不能超过 {max} 个字符")
private String name;
/**
* 厂商名称标识
*/
@Schema(description = "厂商名称标识")
@NotBlank(message = "厂商名称标识不能为空")
@Length(max = 50, message = "厂商名称标识长度不能超过 {max} 个字符")
private String supplier;
/**
* Access Key 或 API Key
*/
@Schema(description = "Access Key 或 API Key")
@NotBlank(message = "Access Key 或 API Key不能为空")
@Length(max = 255, message = "Access Key 或 API Key长度不能超过 {max} 个字符")
private String accessKeyId;
/**
* Access Secret 或 API Secret
*/
@Schema(description = "Access Secret 或 API Secret")
@NotBlank(message = "Access Secret 或 API Secret不能为空")
@Length(max = 255, message = "Access Secret 或 API Secret长度不能超过 {max} 个字符")
private String accessKeySecret;
/**
* 短信签名
*/
@Schema(description = "短信签名")
@NotBlank(message = "短信签名不能为空")
@Length(max = 100, message = "短信签名长度不能超过 {max} 个字符")
private String signature;
/**
* 模板 ID
*/
@Schema(description = "模板 ID")
@NotBlank(message = "模板 ID不能为空")
@Length(max = 50, message = "模板 ID长度不能超过 {max} 个字符")
private String templateId;
/**
* 负载均衡权重
*/
@Schema(description = "负载均衡权重")
private Integer weight;
/**
* 短信自动重试间隔时间(秒)
*/
@Schema(description = "短信自动重试间隔时间(秒)")
private Integer retryInterval;
/**
* 短信重试次数
*/
@Schema(description = "短信重试次数")
private Integer maxRetries;
/**
* 当前厂商的发送数量上限
*/
@Schema(description = "当前厂商的发送数量上限")
private Integer maximum;
/**
* 各个厂商独立配置
*/
@Schema(description = "各个厂商独立配置")
@Length(max = 10000, message = "各个厂商独立配置长度不能超过 {max} 个字符")
private String supplierConfig;
/**
* 是否启用
*/
@Schema(description = "是否启用")
@NotNull(message = "是否启用不能为空")
private Boolean isEnable;
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import java.io.Serial;
import java.io.Serializable;
/**
* 创建或修改短信记录参数
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Data
@Schema(description = "创建或修改短信记录参数")
public class SmsRecordReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置id
*/
@Schema(description = "配置id")
@NotNull(message = "配置id不能为空")
private Long configId;
/**
* 手机号
*/
@Schema(description = "手机号")
@NotBlank(message = "手机号不能为空")
@Length(max = 25, message = "手机号长度不能超过 {max} 个字符")
private String phone;
/**
* 参数配置
*/
@Schema(description = "参数配置")
private String params;
/**
* 发送状态
*/
@Schema(description = "发送状态")
@NotNull(message = "发送状态不能为空")
private Boolean status;
/**
* 返回数据
*/
@Schema(description = "返回数据")
@NotBlank(message = "返回数据不能为空")
@Length(max = 2048, message = "返回数据长度不能超过 {max} 个字符")
private String resMsg;
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.resp;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.common.model.resp.BaseDetailResp;
import top.continew.starter.security.mask.annotation.JsonMask;
import java.io.Serial;
/**
* 短信服务配置详情信息
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Data
@ExcelIgnoreUnannotated
@Schema(description = "短信服务配置详情信息")
public class SmsConfigDetailResp extends BaseDetailResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Schema(description = "名称")
@ExcelProperty(value = "名称")
private String name;
/**
* 厂商名称标识
*/
@Schema(description = "厂商名称标识")
@ExcelProperty(value = "厂商名称标识")
private String supplier;
/**
* Access Key 或 API Key
*/
@Schema(description = "Access Key 或 API Key")
@ExcelProperty(value = "Access Key 或 API Key")
private String accessKeyId;
/**
* Access Secret 或 API Secret
*/
@Schema(description = "Access Secret 或 API Secret")
@ExcelProperty(value = "Access Secret 或 API Secret")
@JsonMask(left = 4, right = 4, character = '*')
private String accessKeySecret;
/**
* 短信签名
*/
@Schema(description = "短信签名")
@ExcelProperty(value = "短信签名")
private String signature;
/**
* 模板 ID
*/
@Schema(description = "模板 ID")
@ExcelProperty(value = "模板 ID")
private String templateId;
/**
* 负载均衡权重
*/
@Schema(description = "负载均衡权重")
@ExcelProperty(value = "负载均衡权重")
private Integer weight;
/**
* 短信自动重试间隔时间(秒)
*/
@Schema(description = "短信自动重试间隔时间(秒)")
@ExcelProperty(value = "短信自动重试间隔时间(秒)")
private Integer retryInterval;
/**
* 短信重试次数
*/
@Schema(description = "短信重试次数")
@ExcelProperty(value = "短信重试次数")
private Integer maxRetries;
/**
* 当前厂商的发送数量上限
*/
@Schema(description = "当前厂商的发送数量上限")
@ExcelProperty(value = "当前厂商的发送数量上限")
private Integer maximum;
/**
* 各个厂商独立配置
*/
@Schema(description = "各个厂商独立配置")
@ExcelProperty(value = "各个厂商独立配置")
private String supplierConfig;
/**
* 是否启用
*/
@Schema(description = "是否启用")
@ExcelProperty(value = "是否启用")
private Boolean isEnable;
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.common.model.resp.BaseResp;
import top.continew.starter.security.mask.annotation.JsonMask;
import java.io.Serial;
import java.time.LocalDateTime;
/**
* 短信服务配置信息
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Data
@Schema(description = "短信服务配置信息")
public class SmsConfigResp extends BaseResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Schema(description = "名称")
private String name;
/**
* 厂商名称标识
*/
@Schema(description = "厂商名称标识")
private String supplier;
/**
* Access Key 或 API Key
*/
@Schema(description = "Access Key 或 API Key")
private String accessKeyId;
/**
* Access Secret 或 API Secret
*/
@Schema(description = "Access Secret 或 API Secret")
@JsonMask(left = 4, right = 4, character = '*')
private String accessKeySecret;
/**
* 短信签名
*/
@Schema(description = "短信签名")
private String signature;
/**
* 模板 ID
*/
@Schema(description = "模板 ID")
private String templateId;
/**
* 负载均衡权重
*/
@Schema(description = "负载均衡权重")
private Integer weight;
/**
* 短信自动重试间隔时间(秒)
*/
@Schema(description = "短信自动重试间隔时间(秒)")
private Integer retryInterval;
/**
* 短信重试次数
*/
@Schema(description = "短信重试次数")
private Integer maxRetries;
/**
* 当前厂商的发送数量上限
*/
@Schema(description = "当前厂商的发送数量上限")
private Integer maximum;
/**
* 各个厂商独立配置
*/
@Schema(description = "各个厂商独立配置")
private String supplierConfig;
/**
* 是否启用
*/
@Schema(description = "是否启用")
private Boolean isEnable;
/**
* 修改人
*/
@Schema(description = "修改人")
private Long updateUser;
/**
* 修改时间
*/
@Schema(description = "修改时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.resp;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.common.model.resp.BaseDetailResp;
import java.io.Serial;
/**
* 短信记录详情信息
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Data
@ExcelIgnoreUnannotated
@Schema(description = "短信记录详情信息")
public class SmsRecordDetailResp extends BaseDetailResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置id
*/
@Schema(description = "配置id")
@ExcelProperty(value = "配置id")
private Long configId;
/**
* 手机号
*/
@Schema(description = "手机号")
@ExcelProperty(value = "手机号")
private String phone;
/**
* 参数配置
*/
@Schema(description = "参数配置")
@ExcelProperty(value = "参数配置")
private String params;
/**
* 发送状态
*/
@Schema(description = "发送状态")
@ExcelProperty(value = "发送状态")
private Boolean status;
/**
* 返回数据
*/
@Schema(description = "返回数据")
@ExcelProperty(value = "返回数据")
private String resMsg;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.resp;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import top.continew.admin.common.model.resp.BaseResp;
import java.io.Serial;
import java.time.*;
/**
* 短信记录信息
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Data
@Schema(description = "短信记录信息")
public class SmsRecordResp extends BaseResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置id
*/
@Schema(description = "配置id")
private Long configId;
/**
* 手机号
*/
@Schema(description = "手机号")
private String phone;
/**
* 参数配置
*/
@Schema(description = "参数配置")
private String params;
/**
* 发送状态
*/
@Schema(description = "发送状态")
private Boolean status;
/**
* 返回数据
*/
@Schema(description = "返回数据")
private String resMsg;
/**
* 修改人
*/
@Schema(description = "修改人")
private Long updateUser;
/**
* 修改时间
*/
@Schema(description = "修改时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.service;
import top.continew.starter.extension.crud.service.BaseService;
import top.continew.admin.system.model.query.SmsConfigQuery;
import top.continew.admin.system.model.req.SmsConfigReq;
import top.continew.admin.system.model.resp.SmsConfigDetailResp;
import top.continew.admin.system.model.resp.SmsConfigResp;
/**
* 短信服务配置业务接口
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
public interface SmsConfigService extends BaseService<SmsConfigResp, SmsConfigDetailResp, SmsConfigQuery, SmsConfigReq> {}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.service;
import top.continew.starter.extension.crud.service.BaseService;
import top.continew.admin.system.model.query.SmsRecordQuery;
import top.continew.admin.system.model.req.SmsRecordReq;
import top.continew.admin.system.model.resp.SmsRecordDetailResp;
import top.continew.admin.system.model.resp.SmsRecordResp;
/**
* 短信记录业务接口
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
public interface SmsRecordService extends BaseService<SmsRecordResp, SmsRecordDetailResp, SmsRecordQuery, SmsRecordReq> {}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.service.impl;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.continew.admin.common.enums.MethodTypeEnum;
import top.continew.admin.system.config.sms.event.SmsEventMessage;
import top.continew.admin.system.config.sms.event.SmsRedisConfig;
import top.continew.admin.system.config.sms.event.SmsRedisMessagePublisher;
import top.continew.admin.system.mapper.SmsConfigMapper;
import top.continew.admin.system.model.entity.SmsConfigDO;
import top.continew.admin.system.model.query.SmsConfigQuery;
import top.continew.admin.system.model.req.SmsConfigReq;
import top.continew.admin.system.model.resp.SmsConfigDetailResp;
import top.continew.admin.system.model.resp.SmsConfigResp;
import top.continew.admin.system.service.SmsConfigService;
import top.continew.starter.extension.crud.service.BaseServiceImpl;
import java.util.List;
/**
* 短信服务配置业务实现
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Service
@RequiredArgsConstructor
public class SmsConfigServiceImpl extends BaseServiceImpl<SmsConfigMapper, SmsConfigDO, SmsConfigResp, SmsConfigDetailResp, SmsConfigQuery, SmsConfigReq> implements SmsConfigService {
@Resource
private SmsRedisMessagePublisher smsRedisMessagePublisher;
@Override
protected void afterAdd(SmsConfigReq req, SmsConfigDO entity) {
super.afterAdd(req, entity);
smsRedisMessagePublisher.publish(SmsRedisConfig.SysSmsChannel, new SmsEventMessage(MethodTypeEnum.ADD, entity
.getId()
.toString()));
}
@Override
protected void afterUpdate(SmsConfigReq req, SmsConfigDO entity) {
super.afterUpdate(req, entity);
smsRedisMessagePublisher.publish(SmsRedisConfig.SysSmsChannel, new SmsEventMessage(MethodTypeEnum.UPDATE, entity
.getId()
.toString()));
}
@Override
protected void afterDelete(List<Long> ids) {
super.afterDelete(ids);
for (Long id : ids) {
smsRedisMessagePublisher.publish(SmsRedisConfig.SysSmsChannel, new SmsEventMessage(MethodTypeEnum.DELETE, id
.toString()));
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.service.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.continew.starter.extension.crud.service.BaseServiceImpl;
import top.continew.admin.system.mapper.SmsRecordMapper;
import top.continew.admin.system.model.entity.SmsRecordDO;
import top.continew.admin.system.model.query.SmsRecordQuery;
import top.continew.admin.system.model.req.SmsRecordReq;
import top.continew.admin.system.model.resp.SmsRecordDetailResp;
import top.continew.admin.system.model.resp.SmsRecordResp;
import top.continew.admin.system.service.SmsRecordService;
/**
* 短信记录业务实现
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Service
@RequiredArgsConstructor
public class SmsRecordServiceImpl extends BaseServiceImpl<SmsRecordMapper, SmsRecordDO, SmsRecordResp, SmsRecordDetailResp, SmsRecordQuery, SmsRecordReq> implements SmsRecordService {}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="top.continew.admin.system.mapper.SmsConfigMapper">
</mapper>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="top.continew.admin.system.mapper.SmsRecordMapper">
</mapper>

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.controller.system;
import top.continew.starter.extension.crud.enums.Api;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.admin.common.controller.BaseController;
import top.continew.admin.system.model.query.SmsConfigQuery;
import top.continew.admin.system.model.req.SmsConfigReq;
import top.continew.admin.system.model.resp.SmsConfigDetailResp;
import top.continew.admin.system.model.resp.SmsConfigResp;
import top.continew.admin.system.service.SmsConfigService;
/**
* 短信服务配置管理 API
*
* @author luoqiz
* @since 2025/03/15 18:41
*/
@Tag(name = "短信服务配置管理 API")
@RestController
@CrudRequestMapping(value = "/system/smsConfig", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
Api.EXPORT})
public class SmsConfigController extends BaseController<SmsConfigService, SmsConfigResp, SmsConfigDetailResp, SmsConfigQuery, SmsConfigReq> {}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.controller.system;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.RestController;
import top.continew.admin.common.controller.BaseController;
import top.continew.admin.system.model.query.SmsRecordQuery;
import top.continew.admin.system.model.req.SmsRecordReq;
import top.continew.admin.system.model.resp.SmsRecordDetailResp;
import top.continew.admin.system.model.resp.SmsRecordResp;
import top.continew.admin.system.service.SmsRecordService;
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.starter.extension.crud.enums.Api;
/**
* 短信记录管理 API
*
* @author luoqiz
* @since 2025/03/15 22:15
*/
@Tag(name = "短信记录管理 API")
@RestController
@CrudRequestMapping(value = "/system/smsRecord", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
Api.EXPORT})
public class SmsRecordController extends BaseController<SmsRecordService, SmsRecordResp, SmsRecordDetailResp, SmsRecordQuery, SmsRecordReq> {
}

View File

@@ -82,7 +82,7 @@ VALUES
(1116, '修改状态', 1110, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:storage:updateStatus', 6, 1, 1, NOW()),
(1117, '设为默认存储', 1110, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:storage:setDefault', 7, 1, 1, NOW()),
( 1180, '终端管理', 1000, 2, '/system/client', 'SystemClient', 'system/client/index', NULL, 'mobile', b'0', b'0', b'0', NULL, 9, 1, 1, NOW()),
(1180, '终端管理', 1000, 2, '/system/client', 'SystemClient', 'system/client/index', NULL, 'mobile', b'0', b'0', b'0', NULL, 9, 1, 1, NOW()),
(1181, '列表', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:list', 1, 1, 1, NOW()),
(1182, '详情', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:detail', 2, 1, 1, NOW()),
(1183, '新增', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:add', 3, 1, 1, NOW()),
@@ -94,6 +94,18 @@ VALUES
(1192, '修改', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:update', 2, 1, 1, NOW()),
(1193, '重置', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:reset', 3, 1, 1, NOW()),
(1194, '短信配置', 1000, 2, '/system/sms/config', 'SmsConfig', 'system/sms/config/index', NULL, 'message', b'0', b'0', b'0', NULL, 6, 1, 1, NOW()),
(1195, '列表', 1194, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsConfig:list', 1, 1, 1, NOW()),
(1196, '详情', 1194, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsConfig:detail', 2, 1, 1, NOW()),
(1197, '新增', 1194, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsConfig:add', 3, 1, 1, NOW()),
(1198, '修改', 1194, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsConfig:update', 4, 1, 1, NOW()),
(1199, '删除', 1194, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsConfig:delete', 5, 1, 1, NOW()),
(1200, '导出', 1194, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsConfig:export', 6, 1, 1, NOW()),
(1201, '短信记录', 1000, 2, '/system/sms/record', 'SmsRecord', 'system/sms/record/index', NULL, NULL, b'0', b'0', b'0', NULL, 1, 1, 1, NOW()),
(1202, '列表', 1201, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsRecord:list', 1, 1, 1, NOW()),
(1203, '删除', 1201, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsRecord:delete', 5, 1, 1, NOW()),
(1204, '导出', 1201, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:smsRecord:export', 6, 1, 1, NOW()),
(2000, '系统监控', 0, 1, '/monitor', 'Monitor', 'Layout', '/monitor/online', 'computer', b'0', b'0', b'0', NULL, 2, 1, 1, NOW()),
(2010, '在线用户', 2000, 2, '/monitor/online', 'MonitorOnline', 'monitor/online/index', NULL, 'user', b'0', b'0', b'0', NULL, 1, 1, 1, NOW()),
(2011, '列表', 2010, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'monitor:online:list', 1, 1, 1, NOW()),

View File

@@ -321,3 +321,42 @@ CREATE TABLE IF NOT EXISTS `sys_client` (
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_client_id`(`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='终端表';
CREATE TABLE IF NOT EXISTS `sys_sms_config` (
`id` bigint NOT NULL COMMENT 'ID',
`name` varchar(255) NOT NULL COMMENT '名称',
`supplier` varchar(50) NOT NULL COMMENT '厂商名称标识',
`access_key_id` varchar(255) NOT NULL COMMENT 'Access Key 或 API Key',
`access_key_secret` varchar(255) NOT NULL COMMENT 'Access Secret 或 API Secret',
`signature` varchar(100) NOT NULL COMMENT '短信签名',
`template_id` varchar(50) NULL DEFAULT NULL COMMENT '模板 ID',
`weight` int NULL DEFAULT 1 COMMENT '负载均衡权重',
`retry_interval` int NULL DEFAULT 5 COMMENT '短信自动重试间隔时间(秒)',
`max_retries` int NULL DEFAULT 0 COMMENT '短信重试次数',
`maximum` int NULL DEFAULT 10000 COMMENT '当前厂商的发送数量上限',
`supplier_config` varchar(10000) NULL DEFAULT NULL COMMENT '各个厂商独立配置',
`is_enable` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否启用',
`create_user` bigint NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint COMMENT '修改人',
`update_time` datetime COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_sys_sms_config_create_user`(`create_user` ASC) USING BTREE,
INDEX `idx_sys_sms_config_update_user`(`update_user` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '短信服务配置表';
CREATE TABLE IF NOT EXISTS `sys_sms_record` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
`config_id` bigint NOT NULL COMMENT '配置id',
`phone` varchar(25) NOT NULL COMMENT '手机号',
`params` varchar(2048) NULL DEFAULT NULL COMMENT '参数配置',
`status` bit(1) NOT NULL COMMENT '发送状态',
`res_msg` varchar(2048) NOT NULL COMMENT '返回数据',
`create_user` bigint NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint COMMENT '修改人',
`update_time` datetime COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_sys_sms_record_create_user`(`create_user` ASC) USING BTREE,
INDEX `idx_sys_sms_record_update_user`(`update_user` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '短信记录表';

View File

@@ -94,6 +94,18 @@ VALUES
(1192, '修改', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:update', 2, 1, 1, NOW()),
(1193, '重置', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:reset', 3, 1, 1, NOW()),
(1194, '短信配置', 1000, 2, '/system/sms/config', 'SmsConfig', 'system/sms/config/index', NULL, 'message', false, false, false, NULL, 6, 1, 1, NOW()),
(1195, '列表', 1194, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsConfig:list', 1, 1, 1, NOW()),
(1196, '详情', 1194, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsConfig:detail', 2, 1, 1, NOW()),
(1197, '新增', 1194, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsConfig:add', 3, 1, 1, NOW()),
(1198, '修改', 1194, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsConfig:update', 4, 1, 1, NOW()),
(1199, '删除', 1194, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsConfig:delete', 5, 1, 1, NOW()),
(1200, '导出', 1194, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsConfig:export', 6, 1, 1, NOW()),
(1201, '短信记录', 1000, 2, '/system/sms/record', 'SmsRecord', 'system/sms/record/index', NULL, NULL, false, false, false, NULL, 1, 1, 1, NOW()),
(1202, '列表', 1201, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsRecord:list', 1, 1, 1, NOW()),
(1203, '删除', 1201, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsRecord:delete', 5, 1, 1, NOW()),
(1204, '导出', 1201, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:smsRecord:export', 6, 1, 1, NOW()),
(2000, '系统监控', 0, 1, '/monitor', 'Monitor', 'Layout', '/monitor/online', 'computer', false, false, false, NULL, 2, 1, 1, NOW()),
(2010, '在线用户', 2000, 2, '/monitor/online', 'MonitorOnline', 'monitor/online/index', NULL, 'user', false, false, false, NULL, 1, 1, 1, NOW()),
(2011, '列表', 2010, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'monitor:online:list', 1, 1, 1, NOW()),

View File

@@ -541,3 +541,71 @@ COMMENT ON COLUMN "sys_client"."create_time" IS '创建时间';
COMMENT ON COLUMN "sys_client"."update_user" IS '修改人';
COMMENT ON COLUMN "sys_client"."update_time" IS '修改时间';
COMMENT ON TABLE "sys_client" IS '终端表';
CREATE TABLE "sys_sms_config" (
"id" int8 NOT NULL,
"name" varchar(255) NOT NULL,
"supplier" varchar(50) NOT NULL,
"access_key_id" varchar(255) NOT NULL,
"access_key_secret" varchar(255) NOT NULL,
"signature" varchar(100) NOT NULL,
"template_id" varchar(50) ,
"weight" int4,
"retry_interval" int4,
"max_retries" int4,
"maximum" int4,
"supplier_config" varchar(10000) ,
"is_enable" bool NOT NULL,
"create_user" int8 NOT NULL,
"create_time" timestamp(6) NOT NULL,
"update_user" int8,
"update_time" timestamp(6),
PRIMARY KEY ("id")
);
CREATE INDEX "idx_sys_sms_config_create_user" ON "sys_sms_config" USING btree ("create_user");
CREATE INDEX "idx_sys_sms_config_update_user" ON "sys_sms_config" USING btree ("update_user");
COMMENT ON COLUMN "sys_sms_config"."id" IS 'ID';
COMMENT ON COLUMN "sys_sms_config"."name" IS '名称';
COMMENT ON COLUMN "sys_sms_config"."supplier" IS '厂商名称标识';
COMMENT ON COLUMN "sys_sms_config"."access_key_id" IS 'Access Key 或 API Key';
COMMENT ON COLUMN "sys_sms_config"."access_key_secret" IS 'Access Secret 或 API Secret';
COMMENT ON COLUMN "sys_sms_config"."signature" IS '短信签名';
COMMENT ON COLUMN "sys_sms_config"."template_id" IS '模板 ID';
COMMENT ON COLUMN "sys_sms_config"."weight" IS '负载均衡权重';
COMMENT ON COLUMN "sys_sms_config"."retry_interval" IS '短信自动重试间隔时间(秒)';
COMMENT ON COLUMN "sys_sms_config"."max_retries" IS '短信重试次数';
COMMENT ON COLUMN "sys_sms_config"."maximum" IS '当前厂商的发送数量上限';
COMMENT ON COLUMN "sys_sms_config"."supplier_config" IS '各个厂商独立配置';
COMMENT ON COLUMN "sys_sms_config"."is_enable" IS '是否启用';
COMMENT ON COLUMN "sys_sms_config"."create_user" IS '创建人';
COMMENT ON COLUMN "sys_sms_config"."create_time" IS '创建时间';
COMMENT ON COLUMN "sys_sms_config"."update_user" IS '修改人';
COMMENT ON COLUMN "sys_sms_config"."update_time" IS '修改时间';
COMMENT ON TABLE "sys_sms_config" IS '短信服务配置表';
CREATE TABLE "sys_sms_record" (
"id" int8 NOT NULL,
"config_id" int8 NOT NULL,
"phone" varchar(25) NOT NULL,
"params" varchar(2048),
"status" varchar(1),
"res_msg" varchar(2048),
"create_user" int8,
"create_time" timestamp(6) NOT NULL,
"update_user" int8,
"update_time" timestamp(6),
PRIMARY KEY ("id")
);
CREATE INDEX "idx_sys_sms_record_create_user" ON "sys_sms_record" USING btree ("create_user");
CREATE INDEX "idx_sys_sms_record_update_user" ON "sys_sms_record" USING btree ( "update_user" );
COMMENT ON COLUMN "sys_sms_record"."id" IS 'ID';
COMMENT ON COLUMN "sys_sms_record"."config_id" IS '配置id';
COMMENT ON COLUMN "sys_sms_record"."phone" IS '手机号';
COMMENT ON COLUMN "sys_sms_record"."params" IS '参数配置';
COMMENT ON COLUMN "sys_sms_record"."status" IS '发送状态';
COMMENT ON COLUMN "sys_sms_record"."res_msg" IS '返回数据';
COMMENT ON COLUMN "sys_sms_record"."create_user" IS '创建人';
COMMENT ON COLUMN "sys_sms_record"."create_time" IS '创建时间';
COMMENT ON COLUMN "sys_sms_record"."update_user" IS '修改人';
COMMENT ON COLUMN "sys_sms_record"."update_time" IS '修改时间';
COMMENT ON TABLE "sys_sms_record" IS '短信记录表';