diff --git a/eladmin-common/pom.xml b/eladmin-common/pom.xml
index 2150b4b..93e9855 100644
--- a/eladmin-common/pom.xml
+++ b/eladmin-common/pom.xml
@@ -23,4 +23,4 @@
${hutool.version}
-
\ No newline at end of file
+
diff --git a/eladmin-common/src/main/java/me/zhengjie/annotation/rest/RedisLock.java b/eladmin-common/src/main/java/me/zhengjie/annotation/rest/RedisLock.java
new file mode 100644
index 0000000..93af5fd
--- /dev/null
+++ b/eladmin-common/src/main/java/me/zhengjie/annotation/rest/RedisLock.java
@@ -0,0 +1,40 @@
+
+
+package me.zhengjie.annotation.rest;
+
+import java.lang.annotation.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Enzo
+ * 使用redis进行分布式锁
+ */
+@Target({ElementType.METHOD,ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RedisLock {
+
+ /**
+ * redis锁 名字
+ */
+ String lockName() default "";
+
+ /**
+ * redis锁 key 支持spel表达式
+ */
+ String key() default "";
+
+ /**
+ * 过期秒数,默认为5毫秒
+ *
+ * @return 轮询锁的时间
+ */
+ int expire() default 5000;
+
+ /**
+ * 超时时间单位
+ *
+ * @return 秒
+ */
+ TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
+}
diff --git a/eladmin-common/src/main/java/me/zhengjie/aspect/RedisLockAspect.java b/eladmin-common/src/main/java/me/zhengjie/aspect/RedisLockAspect.java
new file mode 100644
index 0000000..77ba291
--- /dev/null
+++ b/eladmin-common/src/main/java/me/zhengjie/aspect/RedisLockAspect.java
@@ -0,0 +1,62 @@
+
+
+package me.zhengjie.aspect;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.RequiredArgsConstructor;
+import me.zhengjie.annotation.rest.RedisLock;
+import me.zhengjie.utils.SpelUtil;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author lgh
+ */
+@Aspect
+@Component
+@RequiredArgsConstructor
+public class RedisLockAspect {
+
+ private final RedissonClient redissonClient;
+
+ private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";
+
+ @Around("@annotation(redisLock)")
+ public Object around(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
+ String key = redisLock.key();
+ String lockName = redisLock.lockName();
+ RLock rLock = redissonClient.getLock(getRedisKey(joinPoint, lockName, key));
+ rLock.lock(redisLock.expire(), redisLock.timeUnit());
+ Object result;
+ try {
+ //执行方法
+ result = joinPoint.proceed();
+ } finally {
+ rLock.unlock();
+ }
+ return result;
+ }
+
+ /**
+ * 将spel表达式转换为字符串
+ *
+ * @param joinPoint 切点
+ * @return redisKey
+ */
+ private String getRedisKey(ProceedingJoinPoint joinPoint, String lockName, String spel) {
+ Signature signature = joinPoint.getSignature();
+ MethodSignature methodSignature = (MethodSignature) signature;
+ Method targetMethod = methodSignature.getMethod();
+ Object target = joinPoint.getTarget();
+ Object[] arguments = joinPoint.getArgs();
+ return REDISSON_LOCK_PREFIX + lockName + StrUtil.COLON + SpelUtil.parse(target, spel, targetMethod, arguments);
+ }
+}
diff --git a/eladmin-common/src/main/java/me/zhengjie/config/RedissonAutoConfiguration.java b/eladmin-common/src/main/java/me/zhengjie/config/RedissonAutoConfiguration.java
new file mode 100644
index 0000000..b94cf1c
--- /dev/null
+++ b/eladmin-common/src/main/java/me/zhengjie/config/RedissonAutoConfiguration.java
@@ -0,0 +1,69 @@
+package me.zhengjie.config;
+
+/**
+ * @author Enzo
+ * @date : 2021/9/7
+ */
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.Redisson;
+import org.redisson.config.Config;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.SentinelServersConfig;
+import org.redisson.config.SingleServerConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+@RequiredArgsConstructor
+@ConditionalOnClass(Config.class)
+@EnableConfigurationProperties(RedissonProperties.class)
+public class RedissonAutoConfiguration {
+
+ private final RedissonProperties redissonProperties;
+
+ /**
+ * 哨兵模式自动装配
+ * @return
+ */
+ @Bean
+ @ConditionalOnProperty(name="redisson.master-name")
+ RedissonClient redissonSentinel() {
+ Config config = new Config();
+ SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redissonProperties.getSentinelAddresses())
+ .setMasterName(redissonProperties.getMasterName())
+ .setTimeout(redissonProperties.getTimeout())
+ .setMasterConnectionPoolSize(redissonProperties.getMasterConnectionPoolSize())
+ .setSlaveConnectionPoolSize(redissonProperties.getSlaveConnectionPoolSize());
+ if(StringUtils.isNotBlank(redissonProperties.getPassword())) {
+ serverConfig.setPassword(redissonProperties.getPassword());
+ }
+ return Redisson.create(config);
+ }
+
+ /**
+ * 单机模式自动装配
+ * @return
+ */
+ @Bean
+ @ConditionalOnProperty(name="redisson.address")
+ RedissonClient redissonSingle() {
+ Config config = new Config();
+ SingleServerConfig serverConfig = config.useSingleServer()
+ .setAddress(redissonProperties.getAddress())
+ .setTimeout(redissonProperties.getTimeout())
+ .setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
+ .setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());
+
+ if(StringUtils.isNotBlank(redissonProperties.getPassword())) {
+ serverConfig.setPassword(redissonProperties.getPassword());
+ }
+ return Redisson.create(config);
+ }
+
+}
diff --git a/eladmin-common/src/main/java/me/zhengjie/config/RedissonProperties.java b/eladmin-common/src/main/java/me/zhengjie/config/RedissonProperties.java
new file mode 100644
index 0000000..ce7dd3b
--- /dev/null
+++ b/eladmin-common/src/main/java/me/zhengjie/config/RedissonProperties.java
@@ -0,0 +1,39 @@
+package me.zhengjie.config;
+
+import lombok.Data;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Enzo
+ * @date : 2021/9/7
+ */
+
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "redisson")
+@ConditionalOnProperty("redisson.password")
+public class RedissonProperties {
+
+ private int timeout = 3000;
+
+ private String address;
+
+ private String masterName;
+
+ private String password;
+
+ private int database = 0;
+
+ private String[] sentinelAddresses;
+
+ private int connectionPoolSize = 64;
+
+ private int connectionMinimumIdleSize = 10;
+
+ private int slaveConnectionPoolSize = 250;
+
+ private int masterConnectionPoolSize = 250;
+
+}
diff --git a/eladmin-common/src/main/java/me/zhengjie/constant/SmsConstant.java b/eladmin-common/src/main/java/me/zhengjie/constant/SmsConstant.java
index db903a4..bdc3e6f 100644
--- a/eladmin-common/src/main/java/me/zhengjie/constant/SmsConstant.java
+++ b/eladmin-common/src/main/java/me/zhengjie/constant/SmsConstant.java
@@ -7,35 +7,72 @@ package me.zhengjie.constant;
* 短信发送常量
*/
public class SmsConstant {
- /** APP ID*/
+
+ private SmsConstant() {
+
+ }
+
+
+ /**
+ * APP ID
+ */
public static final String APP_ID = "app1";
- /** "|"分割*/
+ /**
+ * "|"分割
+ */
public static final String VERTICAL_LINE = "\\|";
- /** 时间格式*/
+ /**
+ * 时间格式
+ */
public static final String FORMATE_TIMESTAMP = "yyyyMMddHHmmss";
- /** TOKEN*/
- public static final String TOKEN = "f625d0a23493cd8aeb8ada97da7a7b65";
+ /**
+ * 云峰批次号
+ */
+ public static final String YUN_FENG_BATH_NUM = "bai_ye_send_";
- /** 服务前缀*/
- public static final String SHORT_CHAIN_PREFIX = "s.tuoz.net/s/";
+ /**
+ * 服务前缀
+ */
+ public static final String SHORT_CHAIN_PREFIX = "xx.tuoz.net/s/";
- /** 生成短链*/
- public static final String SHORT_GENERATION_LINK = "http://s.tuoz.net/trans";
-
- /*** 短信url*/
- public static final String SMS_LINK = "http://api.hzdaba.cn/v2/Accounts/baiyekeji_label/Sms/send";
+ /**
+ * 大坝TOKEN
+ */
+ public static final String TOKEN = "f625d0a23493cd8aeb8ada97da7a7b65";
+ /**
+ * 云峰appKey
+ */
+ public static final String YUN_FENG_APP_KEY = "U7GJG5X6zwtQqkpykhG0jDf1bfS76q28";
+ /**
+ * 云峰appSecret
+ */
+ public static final String YUN_FENG_APP_SECRET = "6deccec15874ef40bc4064d95e7e59b6";
+ /**
+ * 生成短链
+ */
+ public static final String SHORT_GENERATION_LINK = "https://xx.tuoz.net/trans/";
+ /**
+ * 云峰请求接口
+ */
+ public static final String YUN_FENG_SMS_LINK = "https://api.zhuanxinyun.com/api/v2/sendSms.json";
+ /*** 短信url*/
+ public static final String DABA_SMS_LINK = "http://api.hzdaba.cn/v2/Accounts/baiyekeji_label/Sms/send";
+ /**
+ * 线上html地址
+ */
+ public static final String LINK_ADDRESS = "https://byhl-openapplet-2glb7cr2d6d33545-1307374163.tcloudbaseapp.com/index.html?sign=1aab672f0a8b88de2d70b325a4ca6e87&t=1631243192&id=";
}
diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/SpelUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/SpelUtil.java
new file mode 100644
index 0000000..2169f0f
--- /dev/null
+++ b/eladmin-common/src/main/java/me/zhengjie/utils/SpelUtil.java
@@ -0,0 +1,52 @@
+
+package me.zhengjie.utils;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.context.expression.MethodBasedEvaluationContext;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import java.lang.reflect.Method;
+
+/**
+ * 解析SPEL 表达式
+ * @author huxingnan
+ * @date 2018/5/21 10:51
+ */
+public class SpelUtil {
+
+
+ /**
+ * 支持 #p0 参数索引的表达式解析
+ * @param rootObject 根对象,method 所在的对象
+ * @param spel 表达式
+ * @param method ,目标方法
+ * @param args 方法入参
+ * @return 解析后的字符串
+ */
+ public static String parse(Object rootObject,String spel, Method method, Object[] args) {
+ if (StrUtil.isBlank(spel)) {
+ return StrUtil.EMPTY;
+ }
+ //获取被拦截方法参数名列表(使用Spring支持类库)
+ LocalVariableTableParameterNameDiscoverer u =
+ new LocalVariableTableParameterNameDiscoverer();
+ String[] paraNameArr = u.getParameterNames(method);
+ if (ArrayUtil.isEmpty(paraNameArr)) {
+ return spel;
+ }
+ //使用SPEL进行key的解析
+ ExpressionParser parser = new SpelExpressionParser();
+ //SPEL上下文
+ StandardEvaluationContext context = new MethodBasedEvaluationContext(rootObject,method,args,u);
+ //把方法参数放入SPEL上下文中
+ for (int i = 0; i < paraNameArr.length; i++) {
+ context.setVariable(paraNameArr[i], args[i]);
+ }
+ return parser.parseExpression(spel).getValue(context, String.class);
+ }
+
+}
diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolSendMessage.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolSendMessage.java
new file mode 100644
index 0000000..1877b2a
--- /dev/null
+++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolSendMessage.java
@@ -0,0 +1,46 @@
+package me.zhengjie.config.thread;
+
+import me.zhengjie.modules.constant.DefaultConstant;
+import org.apache.tomcat.util.threads.ThreadPoolExecutor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Enzo
+ * 线程池配置总类,用于配置线程池
+ */
+@Configuration
+@EnableAsync
+public class ThreadPoolSendMessage {
+
+
+ /**
+ * produce
+ */
+ @Value(value = "${save.task.sendMessage.corePoolSize}")
+ private int saveCorePoolSize = 2;
+ @Value(value = "${save.task.sendMessage.maxPoolSize}")
+ private int saveMaxPoolSize = 16;
+ @Value(value = "${save.task.sendMessage.queueCapacity}")
+ private int saveQueueCapacity = 3;
+
+
+ @Bean(value = "sendMessageTaskExecutor")
+ public Executor SendBigDataTaskExecutor(){
+ return new ThreadPoolExecutor(saveCorePoolSize,
+ saveMaxPoolSize,
+ DefaultConstant.THREE_NUMBER,
+ TimeUnit.SECONDS,
+ new LinkedBlockingDeque<>(saveQueueCapacity),
+ Executors.defaultThreadFactory(),
+ new ThreadPoolExecutor.DiscardOldestPolicy());
+ }
+
+}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/constant/DefaultConstant.java b/eladmin-system/src/main/java/me/zhengjie/modules/constant/DefaultConstant.java
index 20693ab..ed4876e 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/constant/DefaultConstant.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/constant/DefaultConstant.java
@@ -39,5 +39,15 @@ public class DefaultConstant {
*/
public static final int TEN_NUMBER = 10;
+ /**
+ * 10
+ */
+ public static final int ELEVEN_NUMBER = 11;
+
+
+ /**
+ * 999999L
+ */
+ public static final int SIX_LARGEST_NUMBER = 999999;
}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java
index fba604f..e7c1b06 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java
@@ -119,6 +119,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/druid/**").permitAll()
// 放行发送短信接口 By Enzo
.antMatchers("/api/tbSendSms/url/**").permitAll()
+
+ .antMatchers("/api/smsConfiguration/detail").permitAll()
+ // 爬取数据请求 用户小程序过审 By Enzo
+ .antMatchers("/api/consult/**").permitAll()
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
index 2ec7e64..f881586 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
@@ -22,7 +22,6 @@ import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
-import java.io.Serializable;
/**
* @author Zheng Jie
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/sms/domain/SmsConfiguration.java b/eladmin-system/src/main/java/me/zhengjie/modules/sms/domain/SmsConfiguration.java
new file mode 100644
index 0000000..d3ed32e
--- /dev/null
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/sms/domain/SmsConfiguration.java
@@ -0,0 +1,79 @@
+/*
+* Copyright 2019-2020 Zheng Jie
+*
+* 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 me.zhengjie.modules.sms.domain;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.annotations.CreationTimestamp;
+import org.springframework.data.annotation.LastModifiedDate;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+* @website https://el-admin.vip
+* @description /
+* @author Enzo
+* @date 2021-09-07
+**/
+@Data
+@Entity
+@Table(name="tb_sms_configuration")
+public class SmsConfiguration implements Serializable {
+
+ @Id
+ @Column(name = "id")
+ @ApiModelProperty(value = "配置id")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "user_id")
+ @ApiModelProperty(value = "角色ID")
+ private Long userId;
+
+ @Column(name = "message_content")
+ @ApiModelProperty(value = "短信内容")
+ private String messageContent;
+
+ @Column(name = "picture_path")
+ @ApiModelProperty(value = "图片路径")
+ private String picturePath;
+
+ @Column(name = "image_url")
+ @ApiModelProperty(value = "图片路径")
+ private String imageUrl;
+
+ @Column(name = "link_address")
+ @ApiModelProperty(value = "跳转链接")
+ private String linkAddress;
+
+ @CreationTimestamp
+ @Column(name = "create_time")
+ @ApiModelProperty(value = "创建日期")
+ private Timestamp createTime;
+
+ @LastModifiedDate
+ @Column(name = "update_time")
+ @ApiModelProperty(value = "更新时间")
+ private Timestamp updateTime;
+
+ public void copy(SmsConfiguration source){
+ BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
+ }
+}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/sms/repository/SmsConfigurationRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/sms/repository/SmsConfigurationRepository.java
new file mode 100644
index 0000000..e56f976
--- /dev/null
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/sms/repository/SmsConfigurationRepository.java
@@ -0,0 +1,35 @@
+/*
+* Copyright 2019-2020 Zheng Jie
+*
+* 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 me.zhengjie.modules.sms.repository;
+
+import me.zhengjie.modules.sms.domain.SmsConfiguration;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+/**
+* @website https://el-admin.vip
+* @author Enzo
+* @date 2021-09-07
+**/
+public interface SmsConfigurationRepository extends JpaRepository, JpaSpecificationExecutor {
+ /**
+ * 用户id查找
+ * @param userId
+ * @return
+ */
+ SmsConfiguration findByUserId(Long userId);
+
+}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/sms/rest/ConsultController.java b/eladmin-system/src/main/java/me/zhengjie/modules/sms/rest/ConsultController.java
new file mode 100644
index 0000000..2556116
--- /dev/null
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/sms/rest/ConsultController.java
@@ -0,0 +1,66 @@
+package me.zhengjie.modules.sms.rest;
+
+import io.swagger.annotations.Api;
+import lombok.RequiredArgsConstructor;
+import me.zhengjie.annotation.Log;
+import me.zhengjie.domain.vo.ConsultVo;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Enzo
+ * @date : 2021/9/8
+ *
+ */
+@Api("获取咨询类信息")
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/consult")
+public class ConsultController {
+
+ @Log("查询短信配置参数")
+ @GetMapping("/detail")
+ public ResponseEntity