diff --git a/bocloud.sms.booter/pom.xml b/bocloud.sms.booter/pom.xml
new file mode 100644
index 0000000..ca19a22
--- /dev/null
+++ b/bocloud.sms.booter/pom.xml
@@ -0,0 +1,228 @@
+
+
+
+ bocloud.sms
+ com.bocloud
+ 6.5.0-LTS-SZ
+
+ 4.0.0
+ bocloud.sms.booter
+ ${bocloud.booter.version}
+
+
+ jakarta.platform
+ jakarta.jakartaee-api
+ 10.0.0
+ provided
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ provided
+
+
+ org.slf4j
+ slf4j-api
+ 2.0.7
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+ commons-logging
+ commons-logging
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+
+ com.bocloud
+ bocloud.sms.service
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ com.bocloud
+ bocloud.boot.common
+
+
+ commons-logging
+ commons-logging
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+ com.bocloud
+ bocloud.cmp.core
+ ${bocloud.core.version}
+
+
+ com.freedom
+ megatron.microservice
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+ org.springframework
+ spring-websocket
+
+
+ org.springframework
+ spring-messaging
+
+
+ jakarta.websocket
+ jakarta.websocket-api
+ 2.1.1
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.23.1
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ true
+ 21
+ 21
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+
+ com.bocloud.sms.booter.Application
+ true
+ false
+ libs/
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.6.1
+
+
+
+ copy-dependencies
+
+
+ jar
+ jar
+ runtime
+ ${project.build.directory}/libs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bocloud.booter.tomcat
+
+ 6.5.0-LTS-SZ
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+
+
+
+
+ bocloud.booter.tongweb
+
+ 6.5.0-LTS-SZ-TONGWEB
+
+
+
+ com.tongweb
+ tongweb-embed
+ 7.0.E.2
+
+
+ com.tongweb.springboot
+ tongweb-spring-boot-starter
+ 2.x.0.RELEASE
+
+
+ com.tongweb.springboot
+ tongweb-spring-boot-websocket
+ 2.x.0.RELEASE
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/Application.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/Application.java
new file mode 100644
index 0000000..0646dda
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/Application.java
@@ -0,0 +1,20 @@
+package com.bocloud.sms.booter;
+
+import org.springframework.amqp.rabbit.annotation.EnableRabbit;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @author dmw
+ */
+@EnableRabbit
+@EnableScheduling
+@SpringBootApplication
+@ComponentScan(value = {"com.bocloud", "com.megatron"})
+public class Application {
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/AccountCache.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/AccountCache.java
new file mode 100644
index 0000000..08b0a9a
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/AccountCache.java
@@ -0,0 +1,222 @@
+package com.bocloud.sms.booter.config;
+
+import java.util.List;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import com.bocloud.sms.entity.ApiToken;
+import com.bocloud.sms.entity.Role;
+import com.bocloud.sms.entity.Tenant;
+import com.bocloud.sms.entity.User;
+import com.bocloud.sms.entity.UserGroup;
+import com.bocloud.sms.repository.ApiTokenRepository;
+import com.bocloud.sms.repository.RoleRepository;
+import com.bocloud.sms.repository.TenantRepository;
+import com.bocloud.sms.repository.UserGroupRepository;
+import com.bocloud.sms.repository.UserRepository;
+import com.megatron.common.model.RequestContext;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyl
+ * @since 2020/3/25 周三 14:06
+ */
+@Component
+@Slf4j
+public class AccountCache implements InitializingBean {
+
+ private final StringRedisTemplate redisTemplate;
+ private final TenantRepository tenantRepository;
+ private final UserRepository userRepository;
+ private final RoleRepository roleRepository;
+ private final UserGroupRepository userGroupRepository;
+ private final ApiTokenRepository apiTokenRepository;
+ private final ThreadPoolTaskExecutor taskExecutor;
+
+ public AccountCache(StringRedisTemplate redisTemplate, TenantRepository tenantRepository,
+ UserRepository userRepository, RoleRepository roleRepository, UserGroupRepository userGroupRepository,
+ ApiTokenRepository apiTokenRepository, ThreadPoolTaskExecutor taskExecutor) {
+ this.redisTemplate = redisTemplate;
+ this.tenantRepository = tenantRepository;
+ this.userRepository = userRepository;
+ this.roleRepository = roleRepository;
+ this.userGroupRepository = userGroupRepository;
+ this.apiTokenRepository = apiTokenRepository;
+ this.taskExecutor = taskExecutor;
+ }
+
+ public void putAccountCache(RequestContext.Catalog catalog, Long id, String account) {
+ String key = catalog.name() + "_" + id;
+ this.redisTemplate.opsForValue().set(key, account);
+ }
+
+ public void putNameCache(RequestContext.Catalog catalog, Long id, String name) {
+ String key = catalog.name() + "_Name_" + id;
+ this.redisTemplate.opsForValue().set(key, name);
+ }
+
+ public void putRoleCache(Long id, String name) {
+ this.redisTemplate.opsForValue().set("Role_Name_" + id, name);
+ }
+
+ public void putUserGroupCache(Long id, String name) {
+ this.redisTemplate.opsForValue().set("Group_Name_" + id, name);
+ }
+
+ public void putApiTokenCache(String token, String apis) {
+ this.redisTemplate.opsForValue().set("Api_Token_" + token, apis);
+ }
+
+ /**
+ * 获取缓存中用户账号
+ *
+ * @param id
+ * 用户id
+ * @return
+ */
+ public String getUserAccount(Long id) {
+ return redisTemplate.opsForValue().get(RequestContext.Catalog.User.name() + "_" + id);
+ }
+
+ /**
+ * 获取缓存中用户名称
+ *
+ * @param id
+ * 用户id
+ * @return
+ */
+ public String getUserName(Long id) {
+ return redisTemplate.opsForValue().get(RequestContext.Catalog.User.name() + "_Name_" + id);
+ }
+
+ /**
+ * 获取缓存中租户账号
+ *
+ * @param id
+ * 租户id
+ * @return
+ */
+ public String getTenantAccount(Long id) {
+ return redisTemplate.opsForValue().get(RequestContext.Catalog.Tenant.name() + "_" + id);
+ }
+
+ /**
+ * 获取缓存中租户名称
+ *
+ * @param id
+ * 租户id
+ * @return
+ */
+ public String getTenantName(Long id) {
+ return redisTemplate.opsForValue().get(RequestContext.Catalog.Tenant.name() + "_Name_" + id);
+ }
+
+ /**
+ * 获取缓存中角色名称
+ *
+ * @param id
+ * 租户id
+ * @return
+ */
+ public String getRoleName(Long id) {
+ return redisTemplate.opsForValue().get("Role_Name_" + id);
+ }
+
+ /**
+ * 获取缓存中用户组名称
+ *
+ * @param id
+ * 租户id
+ * @return
+ */
+ public String getUserGroupName(Long id) {
+ return redisTemplate.opsForValue().get("Group_Name_" + id);
+ }
+
+ public String getApiToken(String api) {
+ return redisTemplate.opsForValue().get("Api_Token_" + api);
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ taskExecutor.execute(this::addTenantCache);
+ taskExecutor.execute(this::addUserCache);
+ taskExecutor.execute(this::addRoleCache);
+ taskExecutor.execute(this::addUserGroupCache);
+ taskExecutor.execute(this::addApiTokenCache);
+ }
+
+ public void addTenantCache() {
+ try {
+ List tenants = tenantRepository.listAll();
+ // 缓存租户账号和租户名
+ for (Tenant tenant : tenants) {
+ if (!tenant.getDeleted()) {
+ putAccountCache(RequestContext.Catalog.Tenant, tenant.getId(), tenant.getAccount());
+ }
+ putNameCache(RequestContext.Catalog.Tenant, tenant.getId(), tenant.getName());
+ }
+ } catch (Exception e) {
+ log.error("put tenant cache error,", e);
+ }
+ }
+
+ public void addUserCache() {
+ try {
+ List users = userRepository.listAll();
+ // 缓存用户账号和用户名
+ for (User user : users) {
+ if (!user.getDeleted()) {
+ putAccountCache(RequestContext.Catalog.User, user.getId(), user.getAccount());
+ }
+ putNameCache(RequestContext.Catalog.User, user.getId(), user.getName());
+ }
+ } catch (Exception e) {
+ log.error("put user cache error,", e);
+ }
+ }
+
+ public void addRoleCache() {
+ try {
+ List roles = roleRepository.list();
+ // 缓存角色名
+ for (Role role : roles) {
+ putRoleCache(role.getId(), role.getName());
+ }
+ } catch (Exception e) {
+ log.error("put role cache error,", e);
+ }
+ }
+
+ public void addUserGroupCache() {
+ try {
+ List groups = userGroupRepository.list();
+ // 缓存角色名
+ for (UserGroup group : groups) {
+ putUserGroupCache(group.getId(), group.getName());
+ }
+ } catch (Exception e) {
+ log.error("put user group cache error,", e);
+ }
+ }
+
+ public void addApiTokenCache() {
+ try {
+ List tokens = apiTokenRepository.listAll();
+ // 缓存角色名
+ for (ApiToken token : tokens) {
+ if (!token.getEnabled()) {
+ continue;
+ }
+ putApiTokenCache(token.getToken(), token.getApis());
+ }
+ } catch (Exception e) {
+ log.error("put api token cache error,", e);
+ }
+ }
+
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/DictCache.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/DictCache.java
new file mode 100644
index 0000000..8d3c7e6
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/DictCache.java
@@ -0,0 +1,63 @@
+package com.bocloud.sms.booter.config;
+
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import com.alibaba.fastjson.JSONObject;
+import com.bocloud.sms.entity.Dictionary;
+import com.bocloud.sms.interfaces.DictService;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyl
+ * @since 2020/3/25 周三 14:06
+ */
+@Component
+@Slf4j
+public class DictCache implements InitializingBean {
+
+ private final StringRedisTemplate redisTemplate;
+ private final DictService dictService;
+ private final ThreadPoolTaskExecutor taskExecutor;
+
+ public DictCache(StringRedisTemplate redisTemplate, DictService dictService, ThreadPoolTaskExecutor taskExecutor) {
+ this.redisTemplate = redisTemplate;
+ this.dictService = dictService;
+ this.taskExecutor = taskExecutor;
+ }
+
+ public void putCache(String code, String value) {
+ String key = Dictionary.class.getSimpleName() + "_" + code;
+ this.redisTemplate.opsForValue().set(key, value);
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ taskExecutor.execute(this::addOsNamesCache);
+ taskExecutor.execute(this::addDataCenterCache);
+ }
+
+ public void addOsNamesCache() {
+ try {
+ List list = dictService.getAllOsName();
+ putCache("OS_CATEGORY_TASK", JSONObject.toJSONString(list));
+ } catch (Exception e) {
+ log.error("put os name cache error,", e);
+ }
+ }
+
+ public void addDataCenterCache() {
+ try {
+ Map map = dictService.getAllDataCenter();
+ putCache("DATA_CENTER", JSONObject.toJSONString(map));
+ } catch (Exception e) {
+ log.error("put data center cache error,", e);
+ }
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/RabbitMQConfiguration.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/RabbitMQConfiguration.java
new file mode 100644
index 0000000..f1bc059
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/RabbitMQConfiguration.java
@@ -0,0 +1,155 @@
+package com.bocloud.sms.booter.config;
+
+import com.bocloud.cmp.boot.model.BoCloudExchange;
+import com.bocloud.cmp.core.encrypt.AbstractEncryptHandler;
+import com.bocloud.sms.booter.listener.BocloudMessageListener;
+import com.megatron.common.utils.IDFactory;
+import com.megatron.common.utils.MapTools;
+import com.megatron.framework.core.CurrentService;
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+import java.util.Map;
+
+/**
+ * rabbitmq配置类
+ *
+ * @author wangyu
+ * @version 1.0
+ * @since 2018年3月30日
+ */
+@Configuration
+public class RabbitMQConfiguration {
+
+ private final ConnectionFactory connectionFactory;
+ private final Map arguments = MapTools.simpleMap("x-ha-policy", "all");
+
+ public RabbitMQConfiguration(ConnectionFactory connectionFactory) {
+ this.connectionFactory = connectionFactory;
+ }
+
+ /**
+ * 声明主题交换机
+ *
+ * @return 交换机
+ */
+ @Bean
+ public TopicExchange topicExchange() {
+ return new TopicExchange(BoCloudExchange.Default.TOPIC.getExchange(), true, true);
+ }
+
+ /**
+ * 声明默认交换机
+ *
+ * @return 交换机
+ */
+ @Bean
+ public DirectExchange defaultExchange() {
+ return new DirectExchange(BoCloudExchange.Default.DIRECT.getExchange(), true, true);
+ }
+
+ @Bean
+ public Binding bindingMessageQueue(CurrentService service) {
+ return BindingBuilder.bind(declareMessageQueue(service)).to(topicExchange()).with("bocloud.message.queue.#");
+ }
+
+ @Bean
+ public MessageConverter messageConverter() {
+ return new Jackson2JsonMessageConverter();
+ }
+
+ @Bean
+ public Queue declareMessageQueue(CurrentService service) {
+ return new Queue("bocloud.message.queue.sms." + service.getToken(), true, false, true, arguments);
+ }
+
+ /**
+ * 声明审计日志队列
+ *
+ * @return 队列
+ */
+ @Bean
+ public Queue declareLogQueue() {
+ return new Queue("bocloud.log.queue", true, false, false, arguments);
+ }
+
+ /**
+ * 声明通知消息队列
+ *
+ * @return 队列
+ */
+ @Bean
+ public Queue declareNoticeQueue() {
+ return new Queue("event.notice.queue", true, false, false, arguments);
+ }
+
+ @Bean
+ public Binding bindingNoticeQueue() {
+ return BindingBuilder.bind(declareNoticeQueue()).to(defaultExchange()).withQueueName();
+ }
+
+ @Bean
+ public Binding bindingLogQueue() {
+ return BindingBuilder.bind(declareLogQueue()).to(defaultExchange()).withQueueName();
+ }
+
+ @Bean
+ @ConditionalOnBean(AbstractEncryptHandler.class)
+ public Queue declareLicenseInstallQueue() {
+ return new Queue("license.install.queue." + IDFactory.instance().uuid(), true, false, true, arguments);
+ }
+
+ @Bean
+ @ConditionalOnBean(AbstractEncryptHandler.class)
+ public Binding bindLicenseInstallQueue() {
+ return BindingBuilder.bind(declareLicenseInstallQueue()).to(defaultExchange()).with("license.install.queue");
+ }
+
+ @Bean
+ @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+ public RabbitTemplate amqpTemplate() {
+ RabbitTemplate amqpTemplate = new RabbitTemplate(connectionFactory);
+ amqpTemplate.setMessageConverter(messageConverter());
+ return amqpTemplate;
+ }
+
+ @Bean
+ public RabbitAdmin rabbitAdmin() {
+ return new RabbitAdmin(amqpTemplate());
+ }
+
+ @Bean
+ public SimpleMessageListenerContainer autoMessageListener(CurrentService service, BocloudMessageListener bocloudMessageListener) {
+ SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
+ container.setQueues(declareMessageQueue(service));
+ // 设置确认模式自动确认
+ container.setAcknowledgeMode(AcknowledgeMode.AUTO);
+ container.setMessageListener(bocloudMessageListener);
+ container.setAmqpAdmin(rabbitAdmin());
+ container.setAutoStartup(true);
+ return container;
+ }
+
+ @Bean
+ @ConditionalOnBean(AbstractEncryptHandler.class)
+ public SimpleMessageListenerContainer licenseInstallListener(AbstractEncryptHandler encryptHandler) {
+ SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
+ // 设置确认模式自动确认
+ container.setQueues(declareLicenseInstallQueue());
+ container.setAcknowledgeMode(AcknowledgeMode.AUTO);
+ container.setMessageListener(encryptHandler);
+ container.setAmqpAdmin(rabbitAdmin());
+ container.setAutoStartup(true);
+ return container;
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/SwaggerConfiguration.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/SwaggerConfiguration.java
new file mode 100644
index 0000000..b9b8420
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/SwaggerConfiguration.java
@@ -0,0 +1,45 @@
+package com.bocloud.sms.booter.config;
+
+import cn.hutool.core.util.RandomUtil;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author dmw
+ */
+@Configuration
+public class SwaggerConfiguration {
+ @Bean
+ public GlobalOpenApiCustomizer orderGlobalOpenApiCustomizer() {
+ return openApi -> {
+ if (openApi.getTags() != null) {
+ openApi.getTags().forEach(tag -> {
+ Map map = new HashMap<>();
+ map.put("x-order", RandomUtil.randomInt(0, 100));
+ tag.setExtensions(map);
+ });
+ }
+ if (openApi.getPaths() != null) {
+ openApi.addExtension("x-production", "BeyondCMP");
+ openApi.getPaths().addExtension("x-sign", RandomUtil.randomInt(1, 100));
+ }
+ };
+ }
+
+ @Bean
+ public OpenAPI customOpenAPI() {
+ return new OpenAPI()
+ .info(new Info().title("系统管理服务API接口文档")
+ .version("6.5.0-LTS")
+ .description("系统管理服务API接口文档")
+ .termsOfService("https://www.bocloud.com")
+ .license(new License().name("Apache 2.0").url("https://www.bocloud.com")));
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WebInterceptorConfiguration.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WebInterceptorConfiguration.java
new file mode 100644
index 0000000..1c5d035
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WebInterceptorConfiguration.java
@@ -0,0 +1,108 @@
+package com.bocloud.sms.booter.config;
+
+import com.bocloud.cmp.boot.config.PagerArgumentResolver;
+import com.bocloud.cmp.boot.interceptor.AccessInterceptor;
+import com.bocloud.cmp.boot.interceptor.LogInterceptor;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.megatron.framework.core.InterceptorBridge;
+import com.megatron.framework.core.config.InterceptorConfiguration;
+import com.megatron.framework.core.domain.InterceptorEntity;
+import lombok.extern.slf4j.Slf4j;
+import org.reflections.Reflections;
+import org.reflections.scanners.Scanner;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.ByteArrayHttpMessageConverter;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+
+import java.nio.charset.Charset;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 拦截器配置类
+ *
+ * @author wangyu
+ * @version 1.0
+ * @since 2018年3月30日
+ */
+@Slf4j
+@Component
+public class WebInterceptorConfiguration implements InterceptorConfiguration {
+
+ private static final String[] ACCESS_EXCLUDES = new String[]{"/*/*.css",
+ "/*/*.js", "/*/*.png", "/*/*.jpg", "/*/*.jpeg", "/*.html", "/*/*.html", "/swagger-resources/**",
+ "/favicon.ico", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/v1/log/**", "/v1/logo", "/v1/configs", "/v1/*/login",
+ "/v1/logview", "/v1/logzip", "/status/**", "/v1/tokens", "/v1/config/captcha/install", "/v1/status/sid",
+ "/v1/config/license/install", "/v1/config/status/", "/v1/status/sids", "/status", "/status/db",
+ "/error", "/v1/*/info", "/v1/*/status", "/v1/config/**", "/v1/status/**", "/v1/config/license",
+ "/v3/api-docs/**", "/v1/autologin", "/v1/single/login"};
+ private static final String[] LOG_EXCLUDES = new String[]{"/*/*.css",
+ "/*/*.js", "/*/*.png", "/*/*.jpg", "/*/*.jpeg", "/*.html", "/*/*.html", "/swagger-resources/**", "/favicon.ico",
+ "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/error", "/v3/api-docs/**"};
+ private static final String[] INCLUDES = new String[]{"/**"};
+ private final LogInterceptor logInterceptor;
+ private final AccessInterceptor accessInterceptor;
+
+ @Autowired
+ public WebInterceptorConfiguration(AccessInterceptor accessInterceptor, LogInterceptor logInterceptor) {
+ this.logInterceptor = logInterceptor;
+ this.accessInterceptor = accessInterceptor;
+ }
+
+ @Override
+ public InterceptorBridge buildBridge() {
+ log.info("start to build interceptor bridge ...");
+ InterceptorEntity accessEntity = InterceptorEntity.builder().interceptor(accessInterceptor).includes(INCLUDES).excludes(ACCESS_EXCLUDES).order(0).build();
+ InterceptorEntity auditLogEntity = InterceptorEntity.builder().interceptor(logInterceptor).includes(INCLUDES).excludes(LOG_EXCLUDES).order(1).build();
+
+ List interceptors = new ArrayList<>();
+ interceptors.add(accessEntity);
+ interceptors.add(auditLogEntity);
+
+ List resolvers = new ArrayList<>();
+ resolvers.add(new PagerArgumentResolver());
+
+ List> converters = new ArrayList<>();
+ converters.add(this.byteConverter());
+ converters.add(this.jsonConverter());
+
+ InterceptorBridge bridge = new InterceptorBridge();
+ bridge.setInterceptors(interceptors);
+ bridge.setResolvers(resolvers);
+ bridge.setMessageConverters(converters);
+
+ log.info("build interceptor bridge success!!!");
+ return bridge;
+ }
+
+ private HttpMessageConverter> byteConverter() {
+ return new ByteArrayHttpMessageConverter();
+ }
+
+ private HttpMessageConverter> jsonConverter() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ Reflections reflections = new Reflections("com", new Scanner[0]);
+ Set> classSet = reflections.getTypesAnnotatedWith(JsonTypeName.class);
+ objectMapper.registerSubtypes(classSet);
+ objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+
+ MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
+ jackson2HttpMessageConverter.setDefaultCharset(Charset.defaultCharset());
+ jackson2HttpMessageConverter.setObjectMapper(objectMapper);
+ jackson2HttpMessageConverter.setPrettyPrint(true);
+ jackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
+ return jackson2HttpMessageConverter;
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WebSocketConfiguration.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WebSocketConfiguration.java
new file mode 100644
index 0000000..d13073e
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WebSocketConfiguration.java
@@ -0,0 +1,71 @@
+package com.bocloud.sms.booter.config;
+
+import com.bocloud.sms.booter.websocket.logview.LogViewHandler;
+import com.bocloud.sms.booter.websocket.message.MessageHandler;
+import com.bocloud.sms.booter.websocket.message.MessageInterceptor;
+import com.bocloud.sms.booter.websocket.upload.UploadServiceHandler;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
+import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
+
+/**
+ * 拦截器配置类
+ *
+ * @author tyl
+ * @version 1.0
+ * @since 2021年3月25日
+ */
+@Configuration
+@EnableWebSocket
+@RequiredArgsConstructor
+public class WebSocketConfiguration implements WebSocketConfigurer {
+
+ private final MessageInterceptor messageInterceptor;
+ private final MessageHandler messageHandler;
+ private final LogViewHandler logViewHandler;
+ private final UploadServiceHandler uploadServiceHandler;
+
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter() {
+ return new ServerEndpointExporter();
+ }
+
+ @Bean
+ public DefaultHandshakeHandler handshakeHandler() {
+ return new DefaultHandshakeHandler();
+ }
+
+ @Bean
+ public ServletServerContainerFactoryBean createWebSocketContainer() {
+ ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
+ container.setMaxTextMessageBufferSize(10240);
+ container.setMaxBinaryMessageBufferSize(5 * 1024 * 1024);
+ return container;
+ }
+
+ @Override
+ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+ // 注册普通消息服务
+ registry.addHandler(messageHandler, "/messageService").addInterceptors(messageInterceptor)
+ .setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*");
+ registry.addHandler(messageHandler, "/sockjs/messageService").addInterceptors(messageInterceptor)
+ .setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*").withSockJS();
+ // 注册日志查看消息服务
+ registry.addHandler(logViewHandler, "/logViewService").addInterceptors(messageInterceptor)
+ .setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*");
+ registry.addHandler(logViewHandler, "/sockjs/logViewService").addInterceptors(messageInterceptor)
+ .setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*").withSockJS();
+ // 普通文件上传消息服务
+ registry.addHandler(this.uploadServiceHandler, "/uploadService").addInterceptors(messageInterceptor)
+ .setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*");
+ registry.addHandler(this.uploadServiceHandler, "/sockjs/uploadService")
+ .addInterceptors(this.messageInterceptor).setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*")
+ .withSockJS();
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WhiteApiCache.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WhiteApiCache.java
new file mode 100644
index 0000000..7c55615
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/config/WhiteApiCache.java
@@ -0,0 +1,39 @@
+package com.bocloud.sms.booter.config;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * api权限白名单设置
+ *
+ * @author tyl
+ * @since 2021/3/9 18:10
+ */
+@Component
+public class WhiteApiCache implements InitializingBean {
+ private final StringRedisTemplate redisTemplate;
+ private final ThreadPoolTaskExecutor taskExecutor;
+
+ public WhiteApiCache(StringRedisTemplate redisTemplate, ThreadPoolTaskExecutor taskExecutor) {
+ this.redisTemplate = redisTemplate;
+ this.taskExecutor = taskExecutor;
+ }
+
+
+ @Override
+ public void afterPropertiesSet() {
+ taskExecutor.execute(() -> {
+ //设置白名单
+ List whiteList = Lists.newArrayList("^GET:/v1/users/permissions$",
+ "^GET:/v1/login/detail$", "^GET:/v1/messages$", "^GET:/v1/token$",
+ "^POST:/v1/users/logout$", "^POST:/v1/tenants/logout$", "^GET:/v1/config/license$", "^GET:/v1/roles/ids$");
+ redisTemplate.opsForValue().set("permission_white", JSONObject.toJSONString(whiteList));
+ });
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/AdmissionController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/AdmissionController.java
new file mode 100644
index 0000000..2239f2d
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/AdmissionController.java
@@ -0,0 +1,107 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Admission;
+import com.bocloud.sms.interfaces.AdmissionService;
+import com.bocloud.sms.model.AdmissionModel;
+import com.bocloud.sms.service.utils.AdmissionUtil;
+import com.megatron.common.model.*;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * ip访问限制控制器
+ *
+ * @author wangyu
+ * @version 4.2.1-SNAPSHOT
+ * @since 2019/11/12
+ */
+@RestController
+@RequestMapping("/v1/admissions")
+@Tag(name = "IP限制管理")
+public class AdmissionController {
+
+ private final AdmissionService admissionService;
+ private final AdmissionUtil admissionUtil;
+
+ public AdmissionController(AdmissionService admissionService, AdmissionUtil admissionUtil) {
+ this.admissionService = admissionService;
+ this.admissionUtil = admissionUtil;
+ }
+
+ /**
+ * 获取IP访问限制列表
+ *
+ * @param pager 分页参数
+ * @return 分页数据
+ */
+ @Operation(summary = "查询IP访问限制列表")
+ @GetMapping
+ public GeneralResult> list(Pager pager) {
+ return admissionService.list(pager);
+ }
+
+ /**
+ * 添加IP访问限制
+ *
+ * @param admissionModel ip和类型
+ * @return 是否添加成功
+ */
+ @Operation(summary = "创建IP访问限制")
+ @PostMapping
+ public Result create(@RequestBody AdmissionModel admissionModel,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ Assert.notNull(admissionModel, "请求参数不能为空");
+ Result result = admissionService.create(admissionModel, requestContext);
+ if (result.isSuccess()) {
+ admissionUtil.refresh();
+ }
+ return result;
+ }
+
+ /**
+ * 删除IP访问限制
+ *
+ * @param id 被删除的id
+ * @return 是否删除成功
+ */
+ @Operation(summary = "删除IP访问限制")
+ @DeleteMapping("/{id}")
+ public Result remove(@PathVariable(value = Common.ID) Long id) {
+ Result result = admissionService.remove(id);
+ if (result.isSuccess()) {
+ admissionUtil.refresh();
+ }
+ return result;
+ }
+
+ /**
+ * 查看IP访问限制详情
+ *
+ * @param id 被查看的数据id
+ * @return id访问限制
+ */
+ @Operation(summary = "查看IP访问限制")
+ @GetMapping("/{id}")
+ public GeneralResult detail(@PathVariable(value = Common.ID) Long id) {
+ return admissionService.detail(id);
+ }
+
+ /**
+ * 批量删除IP访问限制
+ *
+ * @param ids 被删除的id列表
+ * @return 删除结果
+ */
+ @Operation(summary = "批量删除IP访问限制")
+ @DeleteMapping
+ public Result batchRemove(@RequestBody List ids) {
+ return admissionService.batchRemove(ids);
+ }
+
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/ApiTokenController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/ApiTokenController.java
new file mode 100644
index 0000000..49c8ebe
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/ApiTokenController.java
@@ -0,0 +1,85 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.ApiToken;
+import com.bocloud.sms.interfaces.ApiTokenService;
+import com.megatron.common.model.GeneralResult;
+import com.megatron.common.model.GridBean;
+import com.megatron.common.model.Pager;
+import com.megatron.common.model.RequestContext;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * api token访问限制控制器
+ */
+@RestController
+@RequestMapping("/v1/api/tokens")
+@Tag(name = "API Token管理")
+public class ApiTokenController {
+
+ @Autowired
+ private ApiTokenService apiTokenService;
+
+ @GetMapping("/check/{token}")
+ @Operation(summary = "查看API Token")
+ public GeneralResult detail(@PathVariable(value = Common.TOKEN) String token) {
+ return apiTokenService.get(token);
+ }
+
+ /**
+ * 创建Token
+ *
+ * @param token
+ * @param context
+ * @return
+ */
+ @PostMapping
+ @Operation(summary = "创建 ApiToken")
+ public GeneralResult create(@RequestBody ApiToken token, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return apiTokenService.create(token, context);
+ }
+
+ /**
+ * 查询Api token列表
+ *
+ * @param pager
+ * @param context
+ * @return
+ */
+ @GetMapping
+ @Operation(summary = "查看API Token列表")
+ public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return apiTokenService.list(pager, context);
+ }
+
+ /**
+ * 修改Api token
+ *
+ * @param token
+ * @param context
+ * @return
+ */
+ @PutMapping
+ @Operation(summary = "修改API Token")
+ public GeneralResult modify(@RequestBody ApiToken token, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return apiTokenService.modify(token, context);
+ }
+
+ /**
+ * 移除Api Token
+ *
+ * @param id
+ * @param context
+ * @return
+ */
+ @DeleteMapping("/{id}")
+ @Operation(summary = "移除Api Token")
+ public GeneralResult remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return apiTokenService.remove(id, context);
+ }
+
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/AutoLoginController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/AutoLoginController.java
new file mode 100644
index 0000000..d100f38
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/AutoLoginController.java
@@ -0,0 +1,29 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.interfaces.AutoLoginService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.view.RedirectView;
+
+@RestController
+@RequestMapping("/v1/autologin")
+@Tag(name = "自动登录")
+public class AutoLoginController {
+
+ @Autowired
+ private AutoLoginService autoLoginService;
+
+ @GetMapping()
+ @Operation(summary = "查看API Token")
+ public RedirectView autoLogin(
+ @RequestHeader(value = "x-forwarded-host", required = false) String host,
+ HttpServletRequest request) {
+ return autoLoginService.autoLogin(host, request);
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/BusinessController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/BusinessController.java
new file mode 100644
index 0000000..a90d42b
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/BusinessController.java
@@ -0,0 +1,221 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Business;
+import com.bocloud.sms.entity.Project;
+import com.bocloud.sms.interfaces.BusinessService;
+import com.bocloud.sms.model.BusinessModel;
+import com.megatron.common.model.*;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * @author tyl
+ * @time 2020/6/3 周三 15:29
+ */
+@RestController
+@RequestMapping("/v1/bizs")
+@Tag(name = "业务管理")
+@Slf4j
+public class BusinessController {
+
+ private final BusinessService businessService;
+
+ public BusinessController(BusinessService businessService) {
+ this.businessService = businessService;
+ }
+
+ /**
+ * 查看业务列表
+ *
+ * @param pager 分页参数
+ * @return 分页查询数据
+ */
+ @Operation(summary = "查看业务列表")
+ @GetMapping
+ public GeneralResult> list(Pager pager,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return businessService.list(pager, requestContext);
+ }
+
+ /**
+ * 添加业务
+ *
+ * @param businessModel 要添加的业务
+ * @param requestContext 请求上下文
+ * @return 是否添加成功
+ */
+ @Operation(summary = "添加业务")
+ @PostMapping
+ public Result create(@RequestBody BusinessModel businessModel,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return businessService.create(businessModel, requestContext);
+ }
+
+ /**
+ * 修改业务
+ *
+ * @param id 被修改的业务id
+ * @param businessModel 修改的数据
+ * @param requestContext 请求上下文
+ * @return 修改结果
+ */
+ @Operation(summary = "修改业务")
+ @PutMapping("/{id}")
+ public Result modify(@PathVariable(value = Common.ID) Long id,
+ @RequestBody BusinessModel businessModel, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return businessService.modify(id, businessModel, requestContext);
+ }
+
+ /**
+ * 删除业务
+ *
+ * @param id 被删除的业务id
+ * @param requestContext 请求上下文
+ * @return 删除结果
+ */
+ @Operation(summary = "删除业务")
+ @DeleteMapping("/{id}")
+ public Result remove(@PathVariable(value = Common.ID) Long id,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return businessService.remove(id, requestContext);
+ }
+
+ /**
+ * 批量删除业务
+ *
+ * @param ids 被删除的业务id列表
+ * @param requestContext 请求上下文
+ * @return 删除结果
+ */
+ @Operation(summary = "批量删除业务")
+ @DeleteMapping
+ public Result batchRemove(@RequestBody List ids,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return businessService.batchRemove(ids, requestContext);
+ }
+
+ /**
+ * 查看业务明细
+ *
+ * @param id 被查看的业务id
+ * @return 业务实体类
+ */
+ @Operation(summary = "查看业务明细")
+ @GetMapping("/{id}")
+ public GeneralResult detail(@PathVariable(value = Common.ID) Long id) {
+ return businessService.detail(id);
+ }
+
+ /**
+ * 查看业务下项目
+ *
+ * @param id 业务id
+ * @return 项目列表
+ */
+ @Operation(summary = "查看业务下项目")
+ @GetMapping("/{id}/projects")
+ public GeneralResult> projects(
+ @PathVariable(value = Common.ID) Long id) {
+ return businessService.listBusinessProject(id);
+ }
+
+ /**
+ * 配置业务项目
+ *
+ * @param id 业务id
+ * @param projectIds 项目id列表
+ * @return 配置结果
+ */
+ @Operation(summary = "配置业务项目")
+ @PatchMapping("/{id}")
+ public Result businessAction(@PathVariable(value = Common.ID) Long id,
+ @RequestBody List projectIds) {
+ return businessService.businessAction(id, projectIds);
+ }
+
+ /**
+ * 导出业务列表
+ *
+ * @param pager 分页参数
+ * @param requestContext 上下文
+ */
+ @Deprecated
+ @Operation(summary = "导出项目列表")
+ @RequestMapping(value = "/export", method = {RequestMethod.GET})
+ public void export(Pager pager,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request,
+ HttpServletResponse response) {
+ List paramList = pager.getParams();
+ try {
+ XSSFWorkbook workbook = businessService.export(paramList, requestContext);
+ // 下载表格到浏览器
+ response.setCharacterEncoding("utf-8");
+ response.setContentType("application/octet-stream");
+ String fileName = "业务统计数据" + System.currentTimeMillis() + ".xlsx";
+ final String userAgent = request.getHeader("user-agent").toLowerCase();
+ if (userAgent.contains("trident") || userAgent.contains("edge")) {
+ fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
+ } else {
+ fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
+ }
+ response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
+ OutputStream os = response.getOutputStream();
+ workbook.write(os);
+ os.flush();
+ os.close();
+ } catch (Exception e) {
+ log.error("export project error,", e);
+ }
+ }
+
+ /**
+ * 下载业务列表模板
+ *
+ * @param response 浏览器响应
+ */
+ @Operation(summary = "下载业务列表模板")
+ @RequestMapping(value = "/import/template", method = {RequestMethod.GET})
+ public void importTemp(HttpServletResponse response) {
+ businessService.importTemp(response);
+ }
+
+ /**
+ * 导入业务列表
+ *
+ * @param requestContext 请求上下文
+ * @param request 请求参数
+ * @return 导入结果
+ */
+ @Operation(summary = "导入业务列表")
+ @PostMapping(value = "/import")
+ public Result importData(@Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request) {
+ MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+ List fileList = multipartRequest.getFiles("file");
+ if (fileList.isEmpty()) {
+ return new Result(false, "文件错误");
+ }
+ MultipartFile multipartFile = fileList.get(0);
+ String originalFilename = multipartFile.getOriginalFilename();
+ // 判断文件名
+ if (originalFilename == null || !(originalFilename.endsWith(".xls") || originalFilename.endsWith(".xlsx"))) {
+ return new Result(false, "文件错误");
+ }
+ return businessService.importData(multipartFile, requestContext);
+ }
+
+}
+
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/ConfigController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/ConfigController.java
new file mode 100644
index 0000000..c52e65f
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/ConfigController.java
@@ -0,0 +1,167 @@
+package com.bocloud.sms.booter.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.bocloud.cmp.boot.model.BoCloudExchange;
+import com.bocloud.sms.model.LicenseMask;
+import com.megatron.common.http.HttpClient;
+import com.megatron.common.model.GeneralResult;
+import com.megatron.common.model.License;
+import com.megatron.common.model.Result;
+import com.megatron.common.utils.Common;
+import com.megatron.framework.core.CurrentService;
+import com.megatron.framework.license.LicenseDaemon;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
+/**
+ * 服务节点信息
+ *
+ * @author weiwei
+ */
+@Slf4j
+@RestController
+@RequestMapping("/v1")
+@Tag(name = "服务节点信息管理")
+public class ConfigController {
+
+ private static final String LICENSE_SUCCESS = "证书激活成功";
+ private static final String LICENSE_FAILED = "证书激活失败";
+ private final LicenseDaemon licenseDaemon;
+ @Value("${service.host:127.0.0.1}")
+ private String host;
+ @Value("${server.port:18088}")
+ private String port;
+ @Autowired
+ private AmqpTemplate amqpTemplate;
+
+ public ConfigController(CurrentService currentService) {
+ this.licenseDaemon = LicenseDaemon.instance(currentService);
+ }
+
+
+ /**
+ * 查询云管license信息
+ *
+ * @return license信息
+ */
+ @Operation(summary = "查询云管license信息")
+ @GetMapping("/config/license")
+ public GeneralResult license() {
+ License license = licenseDaemon.content();
+ return new GeneralResult<>(true, license, "查询成功");
+ }
+
+ /**
+ * 系统状态信息
+ *
+ * @param value 系统url
+ * @return 系统状态信息
+ */
+ @Operation(summary = "系统状态信息")
+ @GetMapping("/config/status")
+ public GeneralResult status(@RequestParam(value = Common.VALUE) String value) {
+ HttpClient client = new HttpClient();
+ String message = client.get(value).getMessage();
+ return JSONObject.parseObject(message, GeneralResult.class);
+ }
+
+ /**
+ * 安装证书
+ *
+ * @param file 证书文件
+ * @return 安装结果
+ */
+ @Operation(summary = "安装证书")
+ @PostMapping("/config/license/install")
+ public Result licenseInstall(@RequestParam("file") MultipartFile file) {
+ if (file.isEmpty()) {
+ return new Result(false, "证书为空!");
+ }
+ Result result;
+ try {
+ result = licenseDaemon.verify(file.getBytes());
+ if (result.isFailed()) {
+ log.error("证书校验失败");
+ return new Result(false, LICENSE_FAILED);
+ }
+ result = licenseDaemon.install(file.getBytes());
+ if (result.isSuccess()) {
+ return new Result(true, LICENSE_SUCCESS);
+ }
+ return new Result(false, LICENSE_FAILED);
+ } catch (IOException e) {
+ log.error("证书激活异常:", e);
+ return new Result(false, LICENSE_FAILED);
+ }
+ }
+
+ /**
+ * 安装license验证码
+ *
+ * @param licenseMask license验证码
+ * @return 安装结果
+ */
+ @Operation(summary = "安装license验证码")
+ @PostMapping("/config/captcha/install")
+ public Result captchaInstall(@RequestBody LicenseMask licenseMask) {
+ try {
+ GeneralResult GeneralResult = licenseDaemon.decode(licenseMask.getLicenseMask());
+ if (GeneralResult.isFailed()) {
+ log.error("证书激活码格式有误,激活失败!");
+ return new Result(false, LICENSE_FAILED);
+ }
+ Result result = licenseDaemon.verify(GeneralResult.getData());
+ if (result.isFailed()) {
+ log.error("证书格式不正确!");
+ return new Result(false, LICENSE_FAILED);
+ }
+ result = licenseDaemon.install(GeneralResult.getData());
+ if (result.isFailed()) {
+ log.error("证书安装失败");
+ return new Result(false, LICENSE_FAILED);
+ }
+ amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
+ "license.install.queue", LICENSE_SUCCESS);
+ return new Result(true, LICENSE_SUCCESS);
+ } catch (Exception e) {
+ log.error("证书激活异常!", e);
+ return new Result(false, LICENSE_FAILED);
+ }
+ }
+
+ /**
+ * 系统sid信息
+ *
+ * @return sid信息
+ */
+ @Operation(summary = "系统状态信息")
+ @GetMapping("/status/sid")
+ public GeneralResult getSid() {
+ HttpClient client = new HttpClient();
+ String url = "http://" + host + ":" + port + "/status/sid";
+ String message = client.get(url).getMessage();
+ return JSONObject.parseObject(message, GeneralResult.class);
+ }
+
+ /**
+ * 系统sid信息
+ *
+ * @return sid信息列表
+ */
+ @Operation(summary = "系统状态信息")
+ @GetMapping("/status/sids")
+ public GeneralResult getSids() {
+ HttpClient client = new HttpClient();
+ String url = "http://" + host + ":" + port + "/status/sids";
+ String message = client.get(url).getMessage();
+ return JSONObject.parseObject(message, GeneralResult.class);
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DepartmentController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DepartmentController.java
new file mode 100644
index 0000000..353d23d
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DepartmentController.java
@@ -0,0 +1,117 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Department;
+import com.bocloud.sms.entity.User;
+import com.bocloud.sms.interfaces.DepartmentService;
+import com.bocloud.sms.model.DepartmentModel;
+import com.megatron.common.model.GeneralResult;
+import com.megatron.common.model.RequestContext;
+import com.megatron.common.model.Result;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 组织管理控制器
+ *
+ * @author tyl
+ * @since 2021/03/25
+ */
+@RestController
+@RequestMapping("/v1/departments")
+@Tag(name = "组织管理")
+public class DepartmentController {
+
+ private final DepartmentService departmentService;
+
+ public DepartmentController(DepartmentService departmentService) {
+ this.departmentService = departmentService;
+ }
+
+ /**
+ * 查询组织机构
+ *
+ * @param parentId 父组织id
+ * @param requestContext 上下文
+ * @return 组织机构列表
+ */
+ @GetMapping
+ @Operation(summary = "组织机构列表显示")
+ public GeneralResult> list(@RequestParam(value = Common.PARENTID) Long parentId, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return departmentService.list(parentId, requestContext);
+ }
+
+ /**
+ * 查询组织机构下的管理员
+ *
+ * @param id 组织id
+ * @param requestContext 上下文
+ * @return 管理员信息
+ */
+ @GetMapping("/{id}/managers")
+ @Operation(summary = "查询组织机构下的管理员")
+ public GeneralResult> listDeptManager(@PathVariable(value = Common.ID) Long id, RequestContext requestContext) {
+ return departmentService.listDeptManager(id, requestContext);
+ }
+
+ /**
+ * 创建组织机构
+ *
+ * @param department 组织
+ * @param requestContext 上下文
+ * @return 创建结果
+ */
+ @Operation(summary = "创建组织机构")
+ @PostMapping
+ public Result create(@RequestBody DepartmentModel department,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return departmentService.create(department, requestContext);
+ }
+
+ /**
+ * 修改组织机构
+ *
+ * @param id 组织id
+ * @param department 组织
+ * @param requestContext 上下文
+ * @return 修改结果
+ */
+ @Operation(summary = "修改组织机构")
+ @PutMapping("/{id}")
+ public Result modify(@PathVariable(value = Common.ID) Long id,
+ @RequestBody DepartmentModel department,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return departmentService.modify(id, department, requestContext);
+ }
+
+ /**
+ * 删除组织机构
+ *
+ * @param id 组织id
+ * @param requestContext 上下文
+ * @return 删除结果
+ */
+ @Operation(summary = "删除组织机构")
+ @DeleteMapping("/{id}")
+ public Result remove(@PathVariable(value = Common.ID) Long id,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return departmentService.remove(id, requestContext);
+ }
+
+ /**
+ * 查询组织机构详情
+ *
+ * @param id 组织id
+ * @return 组织
+ */
+ @Operation(summary = "组织机构详情")
+ @GetMapping("/{id}")
+ public GeneralResult detail(@PathVariable(value = Common.ID) Long id) {
+ return departmentService.detail(id);
+ }
+
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DictController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DictController.java
new file mode 100644
index 0000000..0a57cdf
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DictController.java
@@ -0,0 +1,106 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Dictionary;
+import com.bocloud.sms.interfaces.DictService;
+import com.bocloud.sms.model.DictionaryBean;
+import com.megatron.common.model.GeneralResult;
+import com.megatron.common.model.Result;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 字典信息控制器
+ *
+ * @author dmw
+ */
+@RestController
+@RequestMapping("/v1/dictionaries")
+@Tag(name = "字典信息管理")
+public class DictController {
+ private final DictService dictService;
+
+ public DictController(DictService dictService) {
+ this.dictService = dictService;
+ }
+
+ @Operation(summary = "查询字典树列表")
+ @GetMapping
+ public GeneralResult> list(@RequestParam(value = "pid", required = false) Long pid) {
+ return dictService.list(pid);
+ }
+
+ @Operation(summary = "根据id查询字典")
+ @GetMapping("/{id}")
+ public GeneralResult detail(@PathVariable(value = "id") Long id) {
+ return dictService.detail(id);
+ }
+
+ /**
+ * 根据字典值获取子节点列表
+ *
+ * @param value 字典值
+ * @return 子节点列表
+ */
+ @Operation(summary = "查询系统字典子信息")
+ @GetMapping("/children")
+ public GeneralResult> children(@RequestParam(value = Common.VALUE, required = false) String value,
+ @RequestParam(value = "pid", required = false) Long pid) {
+ return dictService.listChild(value, pid);
+ }
+
+ /**
+ * 查询字典树
+ *
+ * @param value 字典值
+ * @return 字典树
+ */
+ @Operation(summary = "查询字典树")
+ @GetMapping("/children/tree")
+ public GeneralResult> childTree(@RequestParam(value = Common.VALUE, required = false) String value) {
+ return dictService.childTree(value);
+ }
+
+ /**
+ * 创建
+ *
+ * @param dictionary 字典数据
+ * @return 创建结果
+ */
+ @Operation(summary = "新增字典")
+ @PostMapping
+ public GeneralResult create(@RequestBody Dictionary dictionary) {
+ return dictService.create(dictionary);
+ }
+
+ /**
+ * 删除字典
+ *
+ * @param id 字典id
+ * @return 删除结果
+ */
+ @Operation(summary = "删除字典")
+ @DeleteMapping("/{id}")
+ public Result remove(@PathVariable(value = Common.ID) Long id) {
+ return dictService.remove(id);
+ }
+
+ /**
+ * 修改字典
+ *
+ * @param id 字典id
+ * @param bean 字典
+ * @return 修改结果
+ */
+ @Operation(summary = "修改字典")
+ @PutMapping("/{id}")
+ public GeneralResult modify(@PathVariable(value = Common.ID) Long id,
+ @RequestBody DictionaryBean bean) {
+ bean.setId(id);
+ return dictService.modify(bean);
+ }
+
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DispatchController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DispatchController.java
new file mode 100644
index 0000000..9fbbb91
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/DispatchController.java
@@ -0,0 +1,96 @@
+package com.bocloud.sms.booter.controller;
+
+import com.auth0.jwt.interfaces.Claim;
+import com.bocloud.sms.entity.SystemConfig;
+import com.bocloud.sms.repository.SystemConfigRepository;
+import com.megatron.common.utils.Common;
+import com.megatron.common.utils.Tokens;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * @author tyl
+ * {@code @time} 2020/4/24 周五 20:02
+ */
+@Slf4j
+@Controller
+@RequestMapping
+@Tag(name = "跳转控制")
+public class DispatchController {
+
+ private final SystemConfigRepository configRepository;
+ private final StringRedisTemplate redisTemplate;
+
+
+ public DispatchController(SystemConfigRepository systemConfigService, StringRedisTemplate redisTemplate) {
+ this.configRepository = systemConfigService;
+ this.redisTemplate = redisTemplate;
+ }
+
+ /**
+ * 单点登录跳转接口
+ *
+ * @param request 浏览器请求
+ * @param response 浏览器响应
+ * @throws Exception 出现的异常
+ */
+
+ @RequestMapping("/v1/redirect")
+ @Operation(summary = "单点登录跳转")
+ public void redirect(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ //获取登录地址
+ String target = request.getParameter("target");
+ String redirectParameter = request.getParameter("redirect");
+ SystemConfig config;
+ if (target == null || "Manager".equals(target)) {
+ config = configRepository.queryByCode("ManagerAddress");
+ } else {
+ config = configRepository.queryByCode("TenantAddress");
+ }
+ String loginAddress = config.getValue();
+ log.info("#######debuge########the request url is {}", request.getRequestURL() + "?" + request.getQueryString());
+ log.info("#######debuge########the redirect url is {}", redirectParameter);
+ String redirect = Optional.ofNullable(redirectParameter).orElse(loginAddress + "/#/");
+ String token = request.getParameter("token");
+ log.info("#######debuge########the redirect token is {}", token);
+ Claim claim = Tokens.parse(token);
+ if (!Objects.isNull(claim)) {
+ String catalog = claim.asMap().get("catalog").toString();
+ long uuid = Long.parseLong(claim.asMap().get(Common.UUID).toString());
+ String tokenKey = Common.TOKEN + "_" + catalog + "_" + uuid;
+ boolean checkResult = check(token, tokenKey);
+ if (checkResult) {
+ HttpSession session = request.getSession();
+ session.setAttribute("redirect", redirect);
+ session.setAttribute(Common.TOKEN, token);
+ response.sendRedirect(loginAddress + "/#/sso");
+ } else {
+ String replace = redirect.replace("#", "%23");
+ response.sendRedirect(loginAddress + "/#/login?redirect=" + replace);
+ }
+ } else {
+ String replace = redirect.replace("#", "%23");
+ response.sendRedirect(loginAddress + "/#/login?redirect=" + replace);
+ }
+ }
+
+ private boolean check(String token, String tokenKey) {
+ String newTokenCache = (String) this.redisTemplate.opsForHash().get(tokenKey + "_n", Common.TOKEN);
+ String oldTokenCache = this.redisTemplate.opsForValue().get(tokenKey + "_o");
+ if (token.equals(newTokenCache)) {
+ return true;
+ } else {
+ return token.equals(oldTokenCache);
+ }
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/EnvironmentController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/EnvironmentController.java
new file mode 100644
index 0000000..fac6d92
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/EnvironmentController.java
@@ -0,0 +1,99 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Environment;
+import com.bocloud.sms.interfaces.EnvironmentService;
+import com.megatron.common.model.GeneralResult;
+import com.megatron.common.model.GridBean;
+import com.megatron.common.model.Pager;
+import com.megatron.common.model.RequestContext;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 环境实体类Controller
+ *
+ * @author wangshuai
+ * @version 4.1.0-SNAPSHOT
+ * @since 2018/12/24
+ */
+@RestController
+@RequestMapping("/v1/environments")
+@Tag(name = "所属环境")
+public class EnvironmentController {
+ private final EnvironmentService environmentService;
+
+ public EnvironmentController(EnvironmentService environmentService) {
+ this.environmentService = environmentService;
+ }
+
+ /**
+ * 查看环境列表
+ *
+ * @param pager 分页参数
+ * @return 环境列表
+ */
+ @Operation(summary = "获取所属环境列表")
+ @GetMapping
+ public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return environmentService.list(pager, context);
+ }
+
+ /**
+ * 添加环境
+ *
+ * @param environment 环境
+ * @param context 上下文
+ * @return 添加结果
+ */
+ @Operation(summary = "添加所属环境")
+ @PostMapping
+ public GeneralResult create(@RequestBody Environment environment,
+ @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return environmentService.create(environment, context);
+ }
+
+ /**
+ * 修改环境
+ *
+ * @param id 环境id
+ * @param environment 环境
+ * @param context 上下文
+ * @return 修改结果
+ */
+ @Operation(summary = "修改所属环境")
+ @PutMapping("/{id}")
+ public GeneralResult modify(@PathVariable(value = Common.ID) Long id, @RequestBody Environment environment,
+ @Value(Common.REQ_CONTEXT) RequestContext context) {
+ environment.setId(id);
+ return environmentService.modify(environment, context);
+ }
+
+ /**
+ * 删除环境
+ *
+ * @param id 环境id
+ * @param context 上下文
+ * @return 删除结果
+ */
+ @Operation(summary = "删除所属环境")
+ @DeleteMapping("/{id}")
+ public GeneralResult remove(@PathVariable(value = Common.ID) Long id,
+ @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return environmentService.remove(id, context);
+ }
+
+ /**
+ * 查看环境明细
+ *
+ * @param id 环境id
+ * @return 环境
+ */
+ @Operation(summary = "查看所属环境详情")
+ @GetMapping("/{id}")
+ public GeneralResult detail(@PathVariable(value = Common.ID) Long id) {
+ return environmentService.detail(id);
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/GlobalManConfigController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/GlobalManConfigController.java
new file mode 100644
index 0000000..d214a76
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/GlobalManConfigController.java
@@ -0,0 +1,66 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.GlobalManConfig;
+import com.bocloud.sms.interfaces.GlobalManConfigService;
+import com.megatron.common.model.*;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author wpj
+ * @since 2022/9/8
+ */
+@RestController
+@RequestMapping("/v1/global/config")
+@Slf4j
+@Tag(name = "全局运维配置")
+public class GlobalManConfigController {
+
+ private final GlobalManConfigService globalManConfigService;
+
+ public GlobalManConfigController(GlobalManConfigService globalManConfigService) {
+ this.globalManConfigService = globalManConfigService;
+ }
+
+
+ @Operation(summary = "查询周期时间列表")
+ @GetMapping
+ public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return globalManConfigService.list(pager, context);
+ }
+
+
+ @Operation(summary = "创建禁止周期时间")
+ @PostMapping
+ public Result create(@RequestBody GlobalManConfig globalManConfig,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return globalManConfigService.create(globalManConfig, requestContext);
+ }
+
+ @Operation(summary = "修改禁止周期时间")
+ @PutMapping("/{id}")
+ public Result modify(@RequestBody GlobalManConfig globalManConfig,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return globalManConfigService.modify(globalManConfig, requestContext);
+ }
+
+
+ @Operation(summary = "删除禁止周期时间")
+ @DeleteMapping("/{id}")
+ public Result remove(@PathVariable(value = Common.ID) Long id,
+ @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return globalManConfigService.remove(id, requestContext);
+ }
+
+
+ @Operation(summary = "查询当前全局配置是否被禁止")
+ @GetMapping("/isAllow")
+ public Result isAllow(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
+ return globalManConfigService.allow(requestContext);
+ }
+
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/IconController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/IconController.java
new file mode 100644
index 0000000..c01952e
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/IconController.java
@@ -0,0 +1,66 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Icon;
+import com.bocloud.sms.interfaces.IconService;
+import com.megatron.common.model.GeneralResult;
+import com.megatron.common.model.GridBean;
+import com.megatron.common.model.Pager;
+import com.megatron.common.model.RequestContext;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 图标controller层
+ *
+ * @author 胡立伟
+ * @Version 1.0
+ * @since 2020年4月7日
+ */
+@RestController
+@RequestMapping("/v1/icon")
+@Tag(name = "图标管理")
+public class IconController {
+ @Autowired
+ private IconService iconService;
+
+ /**
+ * 图标列表查询
+ *
+ * @return 图标列表
+ */
+ @GetMapping
+ @Operation(summary = "图标列表查询")
+ public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return iconService.list(pager, context);
+ }
+
+ /**
+ * 上传图标
+ *
+ * @param files 图标文件
+ * @param context 上下文
+ * @return 上传结果
+ */
+ @PostMapping()
+ @Operation(summary = "上传图标")
+ public GeneralResult upload(MultipartFile[] files, String category, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return iconService.create(files, category, context);
+ }
+
+ /**
+ * 删除图标
+ *
+ * @param id 图标id
+ * @return 删除结果
+ */
+ @DeleteMapping(value = "/{id}")
+ @Operation(summary = "删除图标")
+ public GeneralResult remove(@PathVariable(value = Common.ID) Long id) {
+ return iconService.remove(id);
+ }
+}
diff --git a/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/LabelController.java b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/LabelController.java
new file mode 100644
index 0000000..ae3e1e9
--- /dev/null
+++ b/bocloud.sms.booter/src/main/java/com/bocloud/sms/booter/controller/LabelController.java
@@ -0,0 +1,88 @@
+package com.bocloud.sms.booter.controller;
+
+import com.bocloud.sms.entity.Label;
+import com.bocloud.sms.interfaces.LabelService;
+import com.megatron.common.model.*;
+import com.megatron.common.utils.Common;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author zhangdi
+ * @since 2018/7/2
+ */
+@RestController
+@RequestMapping("/v1/tags")
+@Tag(name = "标签管理")
+public class LabelController {
+
+ private final LabelService labelService;
+
+ public LabelController(LabelService labelService) {
+ this.labelService = labelService;
+ }
+
+ /**
+ * 获取标签列表
+ *
+ * @param pager 分页参数
+ * @return 标签列表
+ */
+ @Operation(summary = "获取命名规则列表")
+ @GetMapping
+ public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
+ return labelService.list(pager, context);
+ }
+
+ /**
+ * 添加标签
+ *
+ * @param label 标签
+ * @return 添加结果
+ */
+ @Operation(summary = "添加标签")
+ @PostMapping
+ public GeneralResult