1811872455@163.com hai 3 semanas
pai
achega
de93a06bf5
Modificáronse 39 ficheiros con 2707 adicións e 103 borrados
  1. 4 0
      .idea/compiler.xml
  2. 3 0
      .idea/encodings.xml
  3. 7 0
      .idea/misc.xml
  4. 1 0
      pom.xml
  5. 15 0
      storlead-centre-api/pom.xml
  6. 2 2
      storlead-centre-api/src/main/java/com/storlead/centre/app/AppManageApiController.java
  7. 365 0
      storlead-centre-api/src/main/java/com/storlead/centre/system/LoginApiController.java
  8. 308 0
      storlead-centre-api/src/main/java/com/storlead/centre/system/LoginController.java
  9. 40 0
      storlead-centre-api/src/main/java/com/storlead/centre/system/SystemWechatConfigApiController.java
  10. 407 0
      storlead-centre-api/src/main/java/com/storlead/centre/system/UserApiController.java
  11. 124 0
      storlead-centre-api/src/main/java/com/storlead/centre/system/UserController.java
  12. 10 6
      storlead-dependencies/pom.xml
  13. 152 0
      storlead-framework/storlead-auth/src/main/java/com/storlead/framework/auth/vo/LoginUser.java
  14. 6 0
      storlead-framework/storlead-common/pom.xml
  15. 2 2
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/constant/CommonConstant.java
  16. 25 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/constant/RedisKeySaltConstant.java
  17. 86 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/properties/UrlChainDefinitionPorperties.java
  18. 47 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/util/UrlChainBlackAndWhiteUtil.java
  19. 6 6
      storlead-framework/storlead-mybatis/src/main/java/com/storlead/framework/mybatis/service/impl/MyBaseServiceImpl.java
  20. 35 35
      storlead-framework/storlead-redis/src/main/java/com/storlead/framework/redis/config/RedissonConfig.java
  21. 54 0
      storlead-sms/pom.xml
  22. 37 0
      storlead-sms/src/main/java/com/storlead/sms/constants/SmsTemplateConstants.java
  23. 47 0
      storlead-sms/src/main/java/com/storlead/sms/controller/SmsLogApiController.java
  24. 452 0
      storlead-sms/src/main/java/com/storlead/sms/exception/SMSException.java
  25. 16 0
      storlead-sms/src/main/java/com/storlead/sms/mapper/SmsLogMapper.java
  26. 73 0
      storlead-sms/src/main/java/com/storlead/sms/pojo/entity/SmsLogEntity.java
  27. 23 0
      storlead-sms/src/main/java/com/storlead/sms/service/SmsLogService.java
  28. 91 0
      storlead-sms/src/main/java/com/storlead/sms/service/impl/SmsLogServiceImpl.java
  29. 160 0
      storlead-sms/src/main/java/com/storlead/util/SmsUtil.java
  30. 23 0
      storlead-sms/src/main/resources/mapper/SmsLogMapper.xml
  31. 2 11
      storlead-user/src/main/java/com/storlead/user/controller/UserApiController.java
  32. 0 23
      storlead-user/src/main/java/com/storlead/user/service/IRoleService.java
  33. 1 2
      storlead-user/src/main/java/com/storlead/user/service/impl/UserRoleServiceImpl.java
  34. 5 5
      storlead-user/src/main/java/com/storlead/user/service/impl/UserServiceImpl.java
  35. 17 0
      storlead-wx/src/main/java/com/storlead/wx/pojo/vo/SummaryInfoVO.java
  36. 13 0
      storlead-wx/src/main/java/com/storlead/wx/properties/CorpWeChatConstants.java
  37. 3 0
      storlead-wx/src/main/java/com/storlead/wx/service/CorpWeChatService.java
  38. 12 8
      storlead-wx/src/main/java/com/storlead/wx/service/impl/CorpWeChatServiceImpl.java
  39. 33 3
      storlead-wx/src/main/java/com/storlead/wx/util/CorpWechatUtil.java

+ 4 - 0
.idea/compiler.xml

@@ -16,12 +16,14 @@
         <module name="storlead-user" />
         <module name="storlead-wx" />
         <module name="storlead-mybatis" />
+        <module name="storlead-sms" />
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel>
       <module name="storlead-ai-api" target="17" />
       <module name="storlead-centre-wx" target="17" />
       <module name="storlead-platform" target="17" />
+      <module name="storlead-util" target="17" />
     </bytecodeTargetLevel>
   </component>
   <component name="JavacSettings">
@@ -35,7 +37,9 @@
       <module name="storlead-core" options="-parameters" />
       <module name="storlead-mybatis" options="-parameters" />
       <module name="storlead-redis" options="-parameters" />
+      <module name="storlead-sms" options="-parameters" />
       <module name="storlead-user" options="-parameters" />
+      <module name="storlead-util" options="-parameters" />
       <module name="storlead-web" options="-parameters" />
       <module name="storlead-wx" options="-parameters" />
     </option>

+ 3 - 0
.idea/encodings.xml

@@ -18,7 +18,10 @@
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-mybatis/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-redis/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-redis/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-framework/storlead-util/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-framework/storlead-util/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-web/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-sms/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-user/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-wx/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-wx/src/main/resources" charset="UTF-8" />

+ 7 - 0
.idea/misc.xml

@@ -8,8 +8,15 @@
         <option value="$PROJECT_DIR$/storlead-framework/pom.xml" />
         <option value="$PROJECT_DIR$/pom.xml" />
         <option value="$PROJECT_DIR$/storlead-wx/pom.xml" />
+        <option value="$PROJECT_DIR$/storlead-framework/storlead-util/pom.xml" />
       </list>
     </option>
+    <option name="ignoredFiles">
+      <set>
+        <option value="$PROJECT_DIR$/storlead-framework/storlead-/pom.xml" />
+        <option value="$PROJECT_DIR$/storlead-framework/storlead-util/pom.xml" />
+      </set>
+    </option>
   </component>
   <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="ms-17" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />

+ 1 - 0
pom.xml

@@ -23,6 +23,7 @@
         <module>storlead-centre-service</module>
         <module>storlead-wx</module>
         <module>storlead-user</module>
+        <module>storlead-sms</module>
     </modules>
 
     <properties>

+ 15 - 0
storlead-centre-api/pom.xml

@@ -24,6 +24,21 @@
             <artifactId>storlead-web</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-user</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-sms</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-wx</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-mybatis</artifactId>

+ 2 - 2
storlead-centre-api/src/main/java/com/storlead/centre/app/AppManageApiController.java

@@ -86,7 +86,7 @@ public class AppManageApiController {
     public Result<?> getHomeApp() {
 
         LambdaQueryWrapper<SysAppInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(SysAppInfoEntity::getIsDelete, CommonConstant.FALSE_FLAG);
+        queryWrapper.eq(SysAppInfoEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
         List<SysAppInfoEntity> apps = sysAppInfoService.list(queryWrapper);
         List<SysAppVO> appTree = SysAppVO.appInfoListToAppTreeVoList(apps);
 
@@ -94,7 +94,7 @@ public class AppManageApiController {
             return Result.result(appTree);
         }
         LambdaQueryWrapper<SysAppPageInfoEntity> queryWra1 = new LambdaQueryWrapper<>();
-        queryWra1.eq(SysAppPageInfoEntity::getIsDelete, CommonConstant.FALSE_FLAG);
+        queryWra1.eq(SysAppPageInfoEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
         List<SysAppPageInfoEntity> appPages = sysAppPageInfoService.list(queryWra1);
         if (CollectionUtils.isEmpty(appPages)) {
             return Result.result(appTree);

+ 365 - 0
storlead-centre-api/src/main/java/com/storlead/centre/system/LoginApiController.java

@@ -0,0 +1,365 @@
+//package com.storlead.centre.system;
+//
+//import cn.hutool.core.util.StrUtil;
+//import cn.hutool.crypto.SecureUtil;
+//import com.alibaba.fastjson.JSONObject;
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.storlead.framework.auth.jwt.JwtUtil;
+//import com.storlead.framework.auth.vo.LoginUser;
+//import com.storlead.framework.common.constant.CommonConstant;
+//import com.storlead.framework.common.constant.RedisKeySaltConstant;
+//import com.storlead.framework.common.ecode.BCryptPasswordEncoder;
+//import com.storlead.framework.common.util.RsaUtils;
+//import com.storlead.framework.redis.RedisService;
+//import com.storlead.framework.util.LoginUserUtil;
+//import com.storlead.framework.web.assemble.Result;
+//import com.storlead.framework.web.enums.ErrorMsgCode;
+//import com.storlead.sms.pojo.entity.SmsLogEntity;
+//import com.storlead.sms.service.SmsLogService;
+//import com.storlead.user.pojo.dto.UserLoginDTO;
+//import com.storlead.user.pojo.entity.DeptEntity;
+//import com.storlead.user.pojo.entity.JobEntity;
+//import com.storlead.user.pojo.entity.UserEntity;
+//import com.storlead.user.service.IDepartService;
+//import com.storlead.user.service.IJobService;
+//import com.storlead.user.service.IUserRoleService;
+//import com.storlead.user.service.IUserService;
+//import com.storlead.wx.service.CorpWeChatService;
+//import io.swagger.annotations.Api;
+//import io.swagger.annotations.ApiOperation;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.codec.binary.Base64;
+//import org.springframework.beans.BeanUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.util.CollectionUtils;
+//import org.springframework.web.bind.annotation.*;
+//
+//import javax.annotation.Resource;
+//import javax.crypto.Mac;
+//import javax.crypto.spec.SecretKeySpec;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.io.IOException;
+//import java.security.InvalidKeyException;
+//import java.security.NoSuchAlgorithmException;
+//import java.util.*;
+//import java.util.concurrent.TimeUnit;
+//import java.util.stream.Collectors;
+//
+///**
+// * @program: sp-sales
+// * @description:
+// * @author: chenkq
+// * @create: 2022-07-15 10:11
+// */
+//@RestController
+//@RequestMapping("/sys/auth")
+//@Api(tags="1.认证接口")
+//@Slf4j
+//public class LoginApiController {
+//
+//    @Resource
+//    private IUserService sysUserService;
+//
+//    @Resource
+//    private RedisService redisService;
+//
+//    @Resource
+//    private SmsLogService smsLogService;
+//
+//    @Resource
+//    private IDepartService departService;
+//
+//    @Value("${environment}")
+//    private  String environment;
+//
+//    @Resource
+//    private IUserRoleService userRoleService;
+//
+//    @Resource
+//    private IJobService jobService;
+//
+//    @Resource
+//    private CorpWeChatService corpWeChatService;
+//
+//    @RequestMapping(value = "/redirect")
+//    @ResponseBody
+//    public Object redirect(HttpServletRequest request, HttpServletResponse response)  throws IOException {
+//        response.sendRedirect("http://www.baidu.com");
+//        return Result.ok("");
+//    }
+//
+//    @RequestMapping(value = "/login", method = RequestMethod.POST)
+//    @ApiOperation(value = "用户登录接口", notes = "用户登录接口")
+//    public Result login(@RequestBody UserLoginDTO loginDTO) {
+//
+//        if (Objects.isNull(loginDTO)) {
+//            return Result.error("参数错误");
+//        }
+//        UserEntity userInfo;
+//        JSONObject obj = new JSONObject();
+//        if (StrUtil.isNotBlank(loginDTO.getWxCode())) {
+//            String code = corpWeChatService.login(loginDTO.getWxCode());
+//            userInfo = sysUserService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getXworkUserId,code));
+//        } else if (StrUtil.isNotBlank(loginDTO.getSmsCode())) {
+//            if (StrUtil.isBlank(loginDTO.getAccount())) {
+//                return Result.error("参数错误");
+//            }
+//            Object var1 = redisService.getCacheObject(RedisKeySaltConstant.REDIS_LOGIN_VALID_CODE_KEY+loginDTO.getAccount());
+//            if (Objects.isNull(var1)) {
+//                return Result.error(ErrorMsgCode.D_400005);
+//            } else {
+//                SmsLogEntity smsLog = (SmsLogEntity) var1;
+//                if (!loginDTO.getSmsCode().equals(smsLog.getVerifyCode())){
+//                    return Result.error(ErrorMsgCode.D_400008);
+//                }
+//                Long currentTime = System.currentTimeMillis();
+//                Long sendTime = smsLog.getSendTime().getTime();
+//                if ((currentTime - sendTime) / 1000 > smsLog.getValidTime()) {
+//                    return Result.error(ErrorMsgCode.D_400007);
+//                }
+//            }
+//            userInfo = sysUserService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getMobile,loginDTO.getAccount()));
+//            redisService.deleteObject(RedisKeySaltConstant.REDIS_LOGIN_VALID_CODE_KEY+loginDTO.getAccount());
+//        } else {
+//            if (StrUtil.isBlank(loginDTO.getAccount()) || StrUtil.isBlank(loginDTO.getPassword())) {
+//                return Result.error("用户名或密码为空");
+//            }
+//            userInfo = sysUserService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getMobile,loginDTO.getAccount()).eq(UserEntity::getIsDelete, CommonConstant.DEL_FLAG_0));
+//            if (Objects.isNull(userInfo)) {
+//                return Result.error("账号不存在");
+//            }
+//
+//            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
+//            String password = "";
+//            if((!environment.equals("prod") && !loginDTO.getPassword().equals("qq123456")) || environment.equals("prod")){
+//                try {
+//                    password = RsaUtils.decryptByPrivateKey(RsaUtils.PRIVATE_KEY, loginDTO.getPassword());
+//                }catch (Exception e) {
+//                    return Result.error("用户名或密码错误");
+//                }
+//            }
+//            if(environment.equals("prod") || (environment.equals("test")
+//                    && !loginDTO.getPassword().equals("qq123456") &&
+//                    !password.equals("qq123456"))) {
+//                if (!bCryptPasswordEncoder.matches(password, userInfo.getPassword())) {
+//                    return Result.error("用户名或密码错误");
+//                }
+//            }
+//            String regex = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z\\W]{8,}$";
+//            String defaultPassWord = "storlead123456";// SystemConfigItemCacheUtil.getDefaultPassWord();
+//
+//            if(password !=null && (!password.matches(regex) || password.equals(defaultPassWord))){
+//                obj.put("status",1);
+//            }else {
+//                obj.put("status",2);
+//            }
+//
+//        }
+//        if (Objects.isNull(userInfo)) {
+//            return Result.error("登录失败,未获取到用户信息");
+//        }
+//        if (!userInfo.getEnabled()) {
+//            return Result.error("该账号用户暂无登录权限");
+//        }
+//
+////        Integer possessMenuCount = menuService.checkUserMenuAccess(userInfo.getId());
+////        if (possessMenuCount == 0) {
+////            return Result.error("暂未获取到菜单权限,请联系管理员分配权限!");
+////        }
+//
+//        LoginUser loginUser = new LoginUser();
+//        BeanUtils.copyProperties(userInfo,loginUser);
+//
+//        if (Objects.nonNull(userInfo.getJobId())) {
+//            JobEntity job = jobService.getById(userInfo.getJobId());
+//            if (Objects.nonNull(job)) {
+//                loginUser.setJobName(job.getName());
+//            }
+//        }
+//
+//        loginUser.setRoleIds(userRoleService.selectUserRoleByUserId(userInfo.getId()));
+//        if (Objects.nonNull(userInfo.getDeptId())) {
+//            DeptEntity dept = departService.getById(userInfo.getDeptId());
+//            if (Objects.nonNull(dept)) {
+//                loginUser.setDeptName(dept.getName());
+//                loginUser.setDeptJobDes(dept.getDeptJobDes());
+//            }
+//        }
+//
+//        //用户登录信息
+//        String jwtToken = JwtUtil.createJWT(JSONObject.toJSONString(loginUser),loginUser.getMobile());
+//        String token = SecureUtil.md5(jwtToken);
+//
+//        String json = JSONObject.toJSONString(loginUser);
+//        redisService.setCacheObject(token, json, 60 * 60 * 24L * 7, TimeUnit.SECONDS);
+//
+//        Map<String, String> apiMap = new HashMap();
+//        redisService.setCacheObject(RedisKeySaltConstant.API_CODE_REDIS + loginUser.getMobile(), apiMap);
+//
+//        obj.put("token", token);
+//        return Result.ok(obj);
+//    }
+//
+//
+//    @ApiOperation("获取当前用户信息")
+//    @PostMapping("/getCurrentUserInfo")
+//    public Object getCurrentUserInfo() {
+//        LoginUser loginUser = LoginUserUtil.getLoginUser();
+//        if (Objects.isNull(loginUser)) {
+//            return Result.error("获取失败,请重新登录");
+//        }
+//        DeptEntity dept = departService.getById(loginUser.getDeptId());
+//        UserEntity sysUser = sysUserService.getById(loginUser.getId());
+//        loginUser.setJobDes(sysUser.getJobDes())
+//                 .setBirthday(sysUser.getBirthday())
+//                 .setEmail(sysUser.getEmail())
+//                 .setMobile(sysUser.getMobile())
+//                 .setSex(sysUser.getSex())
+//                 .setUserName(sysUser.getUserName())
+//                 .setNickName(sysUser.getNickName());
+//        if (Objects.nonNull(dept)) {
+//            loginUser.setDeptJobDes(dept.getDeptJobDes());
+//        }
+//        if (Objects.nonNull(dept)) {
+//            if (StrUtil.isNotBlank(dept.getRouteCode())) {
+//                List<String> codes = Arrays.asList(dept.getRouteCode().split(","));
+//                loginUser.setSubCompanyCode(codes.get(1));
+//                loginUser.setCompanyCode(codes.get(0));
+//            }
+//            loginUser.setDeptCode(dept.getRouteCode());
+//            loginUser.setDeptName(dept.getName());
+//        }
+//
+////        List<MenuEntity> userMenuList = menuService.getUserMenuList(loginUser.getId(),Arrays.asList(0),Arrays.asList(3));
+////        if (!CollectionUtils.isEmpty(userMenuList)) {
+////            loginUser.setBtnRes(userMenuList.stream().map(MenuEntity::getPerms).collect(Collectors.toSet()));
+////        }
+//        return Result.ok(loginUser);
+//    }
+//
+//    @ApiOperation("获取当前用户信息")
+//    @PostMapping("/getH5CurrentUserInfo")
+//    public Object getH5CurrentUserInfo() {
+//        LoginUser loginUser = LoginUserUtil.getLoginUser();
+//        if (Objects.isNull(loginUser)) {
+//            return Result.error("获取失败,请重新登录");
+//        }
+//        DeptEntity dept = departService.getById(loginUser.getDeptId());
+//        UserEntity sysUser = sysUserService.getById(loginUser.getId());
+//        loginUser.setJobDes(sysUser.getJobDes())
+//                .setBirthday(sysUser.getBirthday())
+//                .setEmail(sysUser.getEmail())
+//                .setMobile(sysUser.getMobile())
+//                .setSex(sysUser.getSex())
+//                .setUserName(sysUser.getUserName())
+//                .setNickName(sysUser.getNickName());
+//        if (Objects.nonNull(dept)) {
+//            loginUser.setDeptJobDes(dept.getDeptJobDes());
+//        }
+//        if (Objects.nonNull(dept)) {
+//            if (StrUtil.isNotBlank(dept.getRouteCode())) {
+//                List<String> codes = Arrays.asList(dept.getRouteCode().split(","));
+//                loginUser.setSubCompanyCode(codes.get(1));
+//                loginUser.setCompanyCode(codes.get(0));
+//            }
+//            loginUser.setDeptCode(dept.getRouteCode());
+//            loginUser.setDeptName(dept.getName());
+//        }
+//
+////        List<MenuEntity> userMenuList = menuService.getUserMenuList(loginUser.getId(),Arrays.asList(1),Arrays.asList(1,2,3));
+////        if (!CollectionUtils.isEmpty(userMenuList)) {
+////            List<MenuPermis> permis = userMenuList.stream()
+////                    .map(menu -> {
+////                        MenuPermis mp = new MenuPermis();
+////                        mp.setId(menu.getId());
+////                        mp.setPerm(menu.getPerms());
+////                        mp.setType(menu.getMenuType());
+////                        return mp;
+////                    })
+////                    .collect(Collectors.toList());
+////            loginUser.setPermis(permis);
+////        }
+//        return Result.ok(loginUser);
+//    }
+//
+//    @ApiOperation("获取当前用户信息")
+//    @RequestMapping("/getCurrentUser")
+//    public Object getCurrentUser() {
+//        LoginUser loginUser = LoginUserUtil.getLoginUser();
+//        if (Objects.isNull(loginUser)) {
+//            return Result.error("获取失败,请重新登录");
+//        }
+////        DeptEntity dept = departService.getById(loginUser.getDeptId());
+//        UserEntity sysUser = sysUserService.getById(loginUser.getId());
+//        loginUser.setJobDes(sysUser.getJobDes())
+//                .setBirthday(sysUser.getBirthday())
+//                .setEmail(sysUser.getEmail())
+//                .setMobile(sysUser.getMobile())
+//                .setSex(sysUser.getSex())
+//                .setUserName(sysUser.getUserName())
+//                .setNickName(sysUser.getNickName());
+////        if (Objects.nonNull(dept)) {
+////            loginUser.setDeptJobDes(dept.getDeptJobDes());
+////        }
+////        if (Objects.nonNull(dept)) {
+////            if (StrUtil.isNotBlank(dept.getRouteCode())) {
+////                List<String> codes = Arrays.asList(dept.getRouteCode().split(","));
+////                loginUser.setSubCompanyCode(codes.get(1));
+////                loginUser.setCompanyCode(codes.get(0));
+////            }
+////            loginUser.setDeptCode(dept.getRouteCode());
+////            loginUser.setDeptName(dept.getName());
+////        }
+//        return Result.ok(loginUser);
+//    }
+//
+//    @ApiOperation("获取AccessToken")
+//    @PostMapping("/sendVerifyCode")
+//    public Result sendLoginVerifyCode(String mobile) {
+//        if (StrUtil.isBlank(mobile)) {
+//            return Result.error("参数错误");
+//        }
+//        UserEntity userAccount = sysUserService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getMobile,mobile));
+//        if (userAccount == null) {
+//            return Result.error("手机号错误,该手机号用户不存在");
+//        }
+//        try {
+//            return  smsLogService.sendLoginSmsCode(mobile);
+//        }catch (Exception e) {
+//            return  Result.error(e.getMessage());
+//        }
+//    }
+//
+//
+//
+////    public static void main(String[] args) {
+////
+////        String baseUrl = "https://openapi.liblibai.cloud";
+////
+////        String secretKey = "MyJwnqGd1h_W__ENlx_ywK-RpkHTeJd7";
+////        // 请求API接口的uri地址
+////        String uri = "/api/generate/webui/status";
+////        // 当前毫秒时间戳
+////        Long timestamp = System.currentTimeMillis();
+////        // 随机字符串
+////        String signatureNonce = RandomStringUtils.randomAlphanumeric(10);
+////        // 拼接请求数据
+////        String content = uri + "&" + timestamp + "&" + signatureNonce;
+////
+////        try {
+////            // 生成签名
+////            SecretKeySpec secret = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
+////            Mac mac = Mac.getInstance("HmacSHA1");
+////            mac.init(secret);
+////            String signature =  Base64.encodeBase64URLSafeString(mac.doFinal(content.getBytes()));
+////            String url = baseUrl+uri+"?AccessKey=kaB5IBReZKiU9LiIJPbl6g&Signature="+signature+"&Timestamp="+timestamp+"&SignatureNonce="+signatureNonce;
+////            System.out.println("url :"+url);
+////        } catch (NoSuchAlgorithmException e) {
+////           log.error("NoSuchAlgorithmException -- error--",e);
+////        } catch (InvalidKeyException e) {
+////            log.error("InvalidKeyException -- error--",e);
+////        }
+////    }
+//}

+ 308 - 0
storlead-centre-api/src/main/java/com/storlead/centre/system/LoginController.java

@@ -0,0 +1,308 @@
+package com.storlead.centre.system;
+
+import cn.hutool.crypto.SecureUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.storlead.framework.auth.jwt.JwtUtil;
+import com.storlead.framework.auth.vo.LoginUser;
+import com.storlead.framework.common.constant.DefContants;
+import com.storlead.framework.common.util.ConvertUtils;
+import com.storlead.framework.redis.RedisService;
+import com.storlead.framework.util.LoginUserUtil;
+import com.storlead.framework.web.assemble.Result;
+import com.storlead.user.pojo.entity.DeptEntity;
+import com.storlead.user.pojo.entity.UserEntity;
+import com.storlead.user.pojo.entity.UserForm;
+import com.storlead.user.pojo.vo.WeChatPhoneInfo;
+import com.storlead.user.service.IDepartService;
+import com.storlead.user.service.IJobService;
+import com.storlead.user.service.IUserRoleService;
+import com.storlead.user.service.IUserService;
+import com.storlead.wx.util.WechatPhoneUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author scott
+ * @since 2018-12-17
+ */
+@RestController
+@RequestMapping("/lingcun")
+@Api(tags="5.公共接口")
+@Slf4j
+public class LoginController {
+	@Resource
+	private IUserService sysUserService;
+
+//    @Autowired
+//    private EhCacheService ehCacheService;
+
+	@Resource
+    private IDepartService departService;
+
+	@Resource
+	private IUserRoleService userRoleService;
+
+	@Autowired
+	private RedisService redisService;
+
+	@Resource
+	private IJobService jobService;
+
+
+	@Value("${environment}")
+	private  String environment;
+
+	@Value("${weixin.appid}")
+	private String appid;
+
+	@Value("${weixin.secret}")
+	private String secret;
+
+	private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
+
+
+	@RequestMapping(value = "/phone-login", method = RequestMethod.GET)
+	@ApiOperation(value = "微信授权手机号登录接口", notes = "微信授权手机号登录接口")
+	public Result login(String code) {
+		// 1.请求微信接口服务,获取accessToken
+		cn.hutool.json.JSONObject accessTokenJson = WechatPhoneUtil.getAccessToken(appid, secret);
+		String accessToken = accessTokenJson.get("access_token",String.class);
+//		code = code.replace("\"", "");
+		// 2.请求微信接口服务,获取用户手机号信息
+		cn.hutool.json.JSONObject phoneNumberJson = WechatPhoneUtil.getPhoneNumber(code, accessToken);
+		WeChatPhoneInfo phoneInfo = phoneNumberJson.get("phone_info", WeChatPhoneInfo.class);
+		System.out.println(phoneInfo);
+		String phone = phoneInfo.getPurePhoneNumber();
+		if (StringUtils.isEmpty(phone)){
+			return Result.error("手机号获取失败");
+		}
+		UserEntity userInfo;
+		userInfo = sysUserService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getMobile,phone));
+		if (Objects.isNull(userInfo)) {
+			return Result.error("账号不存在");
+		}
+		if (!userInfo.getEnabled()) {
+			return Result.error("该账号用户暂无登录权限");
+		}
+
+		LoginUser loginUser = new LoginUser();
+		BeanUtils.copyProperties(userInfo,loginUser);
+
+//		if (Objects.nonNull(userInfo.getJobId())) {
+//			JobEntity job = jobService.getById(userInfo.getJobId());
+//			if (Objects.nonNull(job)) {
+//				loginUser.setJobName(job.getName());
+//			}
+//		}
+//
+//		if (Objects.nonNull(userInfo.getDeptId())) {
+//			DeptEntity dept = departService.getById(userInfo.getDeptId());
+//			if (Objects.nonNull(dept)) {
+//				loginUser.setDeptJobDes(dept.getDeptJobDes());
+//			}
+//		}
+
+		//用户登录信息
+		String jwtToken = JwtUtil.createJWT(JSONObject.toJSONString(loginUser),loginUser.getMobile());
+		String token = SecureUtil.md5(jwtToken);
+
+		String json = JSONObject.toJSONString(loginUser);
+		redisService.setCacheObject(token, json, 60 * 60 * 24L, TimeUnit.SECONDS);
+
+//		Map<String, String> apiMap = new HashMap();
+//		redisService.setCacheObject(RedisKeySaltConstant.API_CODE_REDIS + loginUser.getMobile(), apiMap);
+		JSONObject obj = new JSONObject();
+		obj.put("status",1);
+		obj.put("token", token);
+		return Result.ok(obj);
+	}
+//
+//	@RequestMapping(value = "/login", method = RequestMethod.POST)
+//	@ApiOperation(value = "用户登录接口", notes = "用户登录接口")
+//	public Result login(@RequestBody SysLoginModel loginModel){
+//		Result result = new Result<JSONObject>();
+//		String username = loginModel.getUsername();
+//		String password = loginModel.getPassword();
+////		//1. 校验用户是否有效
+//		UserEntity sysUser = sysUserService.getUserByName(username);
+//		result = sysUserService.checkUserIsEffective(sysUser);
+//		if(!result.isSuccess()) {
+//			return result;
+//		}
+////		//2. 校验用户名或密码是否正确
+//		String syspassword = sysUser.getPassword();
+//		BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
+//		if (!bCryptPasswordEncoder.matches(password, syspassword)) {
+//			result.error500("用户名或密码错误");
+//			return result;
+//		}
+//
+//		LoginUser loginUser = new LoginUser();
+//		BeanUtils.copyProperties(sysUser,loginUser);
+//
+//		DeptEntity dept = departService.getById(loginUser.getDeptId());
+//		if (Objects.nonNull(dept)) {
+//			if (StrUtil.isNotBlank(dept.getRouteCode())) {
+//				List<String> codes = Arrays.asList(dept.getRouteCode().split(","));
+//				loginUser.setSubCompanyCode(codes.get(1));
+//				loginUser.setCompanyCode(codes.get(0));
+//			}
+//			loginUser.setDeptCode(dept.getRouteCode());
+//		}
+//
+//		UserRoleType userRoleType = userRoleServicel.getUserRole(sysUser);
+//		sysUser.setRoleType(userRoleType);
+//		loginUser.setRoleType(userRoleType);
+//
+//		//用户登录信息
+//		String jwtToken = JwtUtil.createJWT(JSONObject.toJSONString(loginUser),loginUser.getUserName());
+//		String token = SecureUtil.md5(jwtToken);
+//
+//		String json = JSONObject.toJSONString(loginUser);
+//		redisService.setCacheObject(token, json, 60 * 60 * 24L, TimeUnit.SECONDS);
+//
+//		Map<String, String> apiMap = new HashMap();
+//		redisService.setCacheObject(RedisKeySaltConstant.API_CODE_REDIS + loginUser.getUserName(), apiMap);
+//
+//		JSONObject obj = new JSONObject();
+//		obj.put("token", token);
+//		return Result.ok(obj);
+//	}
+
+
+//	@RequestMapping(value = "/loginByMobile", method = RequestMethod.POST)
+//	@ApiOperation(value = "用户短息登录接口", notes = "用户短息登录接口")
+//	public Result<JSONObject> login(@RequestParam("mobile") @ApiParam(value = "手机号")String mobile,@RequestParam("code") @ApiParam(value = "手机验证码")String code){
+//		Result<JSONObject> result = new Result<JSONObject>();
+//		//1. 校验用户是否有效
+//		User sysUser = sysUserService.getUserByMobile(mobile);
+//		result = sysUserService.checkUserIsEffective(sysUser);
+//		if(!result.isSuccess()) {
+//			return result;
+//		}
+//
+//
+//		//2. 校验验证码是否正确
+//		Result checkCodeReslut = smsService.checkCode(mobile, code);
+//		if(!checkCodeReslut.isSuccess()){
+//			return checkCodeReslut;
+//		}
+//		//用户登录信息
+//		userInfo(sysUser, result);
+//		return result;
+//	}
+
+
+	@ApiOperation("修改密码")
+	@PostMapping("/modifyPass")
+	public Object updateUserPass(@RequestBody @Validated UserForm param) {
+		return sysUserService.updateUserPass(param);
+	}
+
+
+	/**
+	 * 退出登录
+	 * @param request
+	 * @param
+	 * @return
+	 */
+	@RequestMapping(value = "/logout")
+	@ApiOperation(value = "用户退出登录接口", notes = "用户退出登录接口")
+	public Result<Object> logout(HttpServletRequest request) {
+		//用户退出逻辑
+		String token = request.getHeader(DefContants.ACCESS_TOKEN);
+		if(ConvertUtils.isEmpty(token)) {
+			return Result.error("退出登录失败!");
+		}
+		Boolean del = redisService.deleteObject(token);
+		if (del) {
+			return Result.ok("退出登录成功!");
+		} else {
+			Object obj = redisService.getCacheObject(token);
+			if (obj == null) {
+				return Result.error("退出登录成功!");
+			}
+			return Result.error("退出登录失败!");
+		}
+	}
+
+
+	/**
+	 * 用户信息
+	 *
+	 * @param request
+	 * @return
+	 */
+	@GetMapping("/getUserBaseInfo")
+	@ApiOperation(value = "根据token获取用户基本信息", notes = "根据token获取用户基本信息(header中传token)")
+	public Result<JSONObject> getUserBaseInfo(HttpServletRequest request) {
+
+		LoginUser loginUser =  LoginUserUtil.getLoginUser();
+		// 生成token
+		Result<JSONObject> result = new Result<JSONObject>();
+		//用户退出逻辑
+		String token = request.getHeader(DefContants.ACCESS_TOKEN);
+		UserEntity sysUser = sysUserService.getUserByName(loginUser.getUserName());
+		// 获取用户部门信息
+		JSONObject obj = new JSONObject();
+		DeptEntity dept = departService.getById(sysUser.getDeptId());
+		obj.put("dept", dept);
+		obj.put("userInfo", sysUser);
+		result.setResult(obj);
+		result.success("登录成功");
+		return result;
+	}
+//
+//	/**
+//	 * 获取校验码
+//	 */
+//	@GetMapping(value = "/getCheckCode")
+//	public Result<Map<String,String>> getCheckCode(){
+//		Result<Map<String,String>> result = new Result<Map<String,String>>();
+//		Map<String,String> map = new HashMap<String,String>();
+//		try {
+//			String code = RandomUtil.randomString(BASE_CHECK_CODES,4);
+//			String key = MD5Util.MD5Encode(code+System.currentTimeMillis(), "utf-8");
+//			ehCacheService.put(CommonConstant.CAPCHA_CACHE,key, code, 60);
+//			map.put("key", key);
+//			map.put("code",code);
+//			result.setResult(map);
+//			result.setSuccess(true);
+//		} catch (Exception e) {
+//			e.printStackTrace();
+//			result.setSuccess(false);
+//		}
+//		return result;
+//	}
+
+	/**
+	 * 获取手机验证码
+	 * @return
+	 */
+//	@GetMapping(value = "/getPhoneCode")
+//	@ApiOperation(value = "获取手机验证码", notes = "获取手机验证码")
+//	public Result getPhoneCode(@RequestParam("mobile") @ApiParam(value = "手机号") String mobile){
+//		try {
+//			int code = RandomCodeUtil.RandomCheckCode();
+//			return smsService.sendSms(mobile,code+"", SmsTypeEnum.Login_SMS.getCode(),null);
+//		} catch (Exception e) {
+//			e.printStackTrace();
+//		}
+//		return Result.error("发送手机验证码失败");
+//	}
+}

+ 40 - 0
storlead-centre-api/src/main/java/com/storlead/centre/system/SystemWechatConfigApiController.java

@@ -0,0 +1,40 @@
+package com.storlead.centre.system;
+
+import com.storlead.framework.web.assemble.Result;
+import com.storlead.wx.pojo.vo.SystemWechatConfigEntity;
+import com.storlead.wx.service.SystemWechatConfigService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 企业微信secret配置 前端控制器
+ * </p>
+ *
+ * @author chenkq
+ * @since 2022-07-20
+ */
+@RestController
+@RequestMapping("/sys/wechat/config")
+public class SystemWechatConfigApiController {
+
+    @Autowired
+    private SystemWechatConfigService systemWechatConfigService;
+
+    @PostMapping(value = "/save")
+    @ApiOperation(value = "保存企业微信参数配置", notes = "配置系统基础设置")
+    public Result saveSetting(SystemWechatConfigEntity entity) {
+        systemWechatConfigService.saveOrUpdate(entity);
+        return Result.ok();
+    }
+
+    @PostMapping(value = "/get")
+    @ApiOperation(value = "保存企业微信参数配置")
+    public Result<?> getSetting() {
+        SystemWechatConfigEntity setting = systemWechatConfigService.getOne(null);
+        return Result.ok(setting);
+    }
+}

+ 407 - 0
storlead-centre-api/src/main/java/com/storlead/centre/system/UserApiController.java

@@ -0,0 +1,407 @@
+//package com.storlead.centre.system;
+//
+//import cn.hutool.core.util.StrUtil;
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+//import com.baomidou.mybatisplus.core.metadata.IPage;
+//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+//import com.storlead.framework.common.constant.CommonConstant;
+//import com.storlead.framework.common.ecode.PasswordEncoder;
+//import com.storlead.framework.util.LoginUserUtil;
+//import com.storlead.framework.web.assemble.Result;
+//import com.storlead.user.pojo.dto.SetUserDetailDTO;
+//import com.storlead.user.pojo.dto.UserParam;
+//import com.storlead.user.pojo.entity.DeptEntity;
+//import com.storlead.user.pojo.entity.UserEntity;
+//import com.storlead.user.pojo.vo.SetUserDetailVo;
+//import com.storlead.user.pojo.vo.UserVo;
+//import com.storlead.user.service.IDepartService;
+//import com.storlead.user.service.IRoleService;
+//import com.storlead.user.service.IUserRoleService;
+//import com.storlead.user.service.IUserService;
+//import io.swagger.annotations.Api;
+//import io.swagger.annotations.ApiOperation;
+//import io.swagger.annotations.ApiResponse;
+//import io.swagger.annotations.ApiResponses;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.util.StringUtils;
+//import org.springframework.web.bind.annotation.PostMapping;
+//import org.springframework.web.bind.annotation.RequestBody;
+//import org.springframework.web.bind.annotation.RequestMapping;
+//import org.springframework.web.bind.annotation.RestController;
+//
+//import javax.annotation.Resource;
+//import java.util.Arrays;
+//import java.util.List;
+//import java.util.Objects;
+//
+//
+///**
+// * @program: sp-cloud
+// * @description:
+// * @author: chenkq
+// * @create: 2022-05-20 12:08
+// */
+//@Slf4j
+//@Api(tags = "用户: 用户管理")
+//@RestController
+//@RequestMapping("/sys/user")
+//public class UserApiController {
+//
+//    @Resource
+//    private IUserService userService;
+//
+//    @Resource
+//    private IDepartService departService;
+//
+//    @Resource
+//    private PasswordEncoder passwordEncoder;
+//
+//    @ApiOperation("根据部门id查询用户")
+//    @PostMapping("listByDeptId")
+//    public Result listByDeptId(Long deptId) {
+//
+//        List<UserEntity> list = userService.list(
+//                new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getDeptId,deptId)
+//                        .ne(UserEntity::getStatus,Integer.valueOf(5))
+//                        .eq(UserEntity::getIsDelete,0));
+//        return Result.ok(list);
+//    }
+//    @ApiOperation("分页查询用户")
+//    @PostMapping("pagelist")
+//    public Result pagelist(@RequestBody UserParam param) {
+//
+////        param.setCommonQueryOrderBy("UserEntity");
+//
+//        IPage<UserVo> page = new Page<>(param.getPageIndex(),param.getPageSize());
+//        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<UserEntity>(new UserEntity());
+//        queryWrapper.eq(UserEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+//        if (StrUtil.isNotBlank(param.getBlurry())) {
+//            queryWrapper.like(UserEntity::getUserName,param.getBlurry()).or().like(UserEntity::getRealName,param.getBlurry());
+//        }
+//        if (StrUtil.isNotBlank(param.getOrgRouteCode())) {
+//            queryWrapper.likeRight(UserEntity::getOrgRouteCode,param.getOrgRouteCode());
+//        }
+////        if (Objects.isNull(param.getStatus())) {
+////            queryWrapper.ne(UserEntity::getStatus,Integer.valueOf(5));
+////        } else {
+////            queryWrapper.ne(UserEntity::getStatus,param.getStatus());
+////        }
+//        if (!param.getIsIncludeResign()) {
+//            queryWrapper.ne(UserEntity::getStatus,Integer.valueOf(5));
+//        }
+//        queryWrapper.orderByDesc(UserEntity::getEmail);
+////        List<UserVo> us  = userService.listWithScopeVo(page,queryWrapper,param);
+////        if (CollectionUtil.isNotEmpty(us)) {
+////            List<Long> userIds = us.stream().map(UserVo::getId).collect(Collectors.toList());
+////            List<UserRoleEntity> userRolels = userRoleService.selectUserRole(new LambdaQueryWrapper<UserRoleEntity>().in(UserRoleEntity::getUserId,userIds));
+////            if (CollectionUtil.isNotEmpty(userRolels)) {
+////                List<RoleEntity> rs = roleService.list(new LambdaQueryWrapper<RoleEntity>().in(RoleEntity::getId,userRolels.stream().map(UserRoleEntity::getRoleId).collect(Collectors.toList())));
+////                us.forEach(u -> {
+////                    List<RoleEntity> roles = rs.stream().filter(r -> userRolels.stream().anyMatch(ur -> ur.getRoleId().equals(r.getId()) && ur.getUserId().equals(u.getId()))).collect(Collectors.toList());
+////                    if(CollectionUtil.isNotEmpty(roles)) {
+////                        u.setRoleNames(roles.stream().map(RoleEntity::getName).collect(Collectors.toList()));
+////                        u.setRoleIds(roles.stream().map(RoleEntity::getId).collect(Collectors.toList()));
+////                    }
+////                });
+////            }
+////
+////            us.forEach(e -> {
+////                e.setIdNum("");
+////                e.setPassword("");
+////                e.setBankCardNum("");
+////                e.setBankName("");
+////                e.setEducation("");
+////                e.setAddress("");
+////                e.setBirthday(null);
+////                e.setEmail("");
+////            });
+////        }
+//        page.setRecords(null);
+//        return Result.ok(page);
+//    }
+//
+//    @ApiOperation("分页查询用户")
+//    @PostMapping("pageScopelist")
+//    public Result pageScopelist(@RequestBody UserParam param) {
+//
+//        IPage<UserVo> page = new Page<>(param.getPageIndex(),param.getPageSize());
+//        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<UserEntity>(new UserEntity());
+//        queryWrapper.eq(UserEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+//        if (StrUtil.isNotBlank(param.getBlurry())) {
+//            queryWrapper.like(UserEntity::getUserName,param.getBlurry()).or().like(UserEntity::getRealName,param.getBlurry());
+//        }
+//        if (StrUtil.isNotBlank(param.getOrgRouteCode())) {
+//            queryWrapper.likeRight(UserEntity::getOrgRouteCode,param.getOrgRouteCode());
+//        }
+//        if (!param.getIsIncludeResign()) {
+//            queryWrapper.ne(UserEntity::getStatus,Integer.valueOf(5));
+//        }
+//        queryWrapper.orderByDesc(UserEntity::getEmail);
+////        List<UserVo> us  = userService.listWithScopeVo(page,queryWrapper,param);
+////        if (CollectionUtil.isNotEmpty(us)) {
+////            List<Long> userIds = us.stream().map(UserVo::getId).collect(Collectors.toList());
+////            List<UserRoleEntity> userRolels = userRoleService.selectUserRole(new LambdaQueryWrapper<UserRoleEntity>().in(UserRoleEntity::getUserId,userIds));
+////            if (CollectionUtil.isNotEmpty(userRolels)) {
+////                List<RoleEntity> rs = roleService.list(new LambdaQueryWrapper<RoleEntity>().in(RoleEntity::getId,userRolels.stream().map(UserRoleEntity::getRoleId).collect(Collectors.toList())));
+////                us.forEach(u -> {
+////                    List<RoleEntity> roles = rs.stream().filter(r -> userRolels.stream().anyMatch(ur -> ur.getRoleId().equals(r.getId()) && ur.getUserId().equals(u.getId()))).collect(Collectors.toList());
+////                    if(CollectionUtil.isNotEmpty(roles)) {
+////                        u.setRoleNames(roles.stream().map(RoleEntity::getName).collect(Collectors.toList()));
+////                        u.setRoleIds(roles.stream().map(RoleEntity::getId).collect(Collectors.toList()));
+////                    }
+////                });
+////            }
+////
+////            us.forEach(e -> {
+////                e.setIdNum("");
+////                e.setPassword("");
+////                e.setBankCardNum("");
+////                e.setBankName("");
+////                e.setEducation("");
+////                e.setAddress("");
+////                e.setBirthday(null);
+////                e.setEmail("");
+////            });
+////        }
+//        page.setRecords(null);
+//        return Result.ok(page);
+//    }
+//
+//    @ApiOperation("删除人员数据")
+//    @PostMapping("delete")
+//    public Result delete(Long [] ids) {
+//        if (ids == null || ids.length == 0) {
+//            return Result.error("参数错误");
+//        }
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper();
+//        update.in(UserEntity::getId,Arrays.asList(ids));
+//        update.set(UserEntity::getIsDelete,1);
+//        userService.update(update);
+//        return Result.ok();
+//    }
+//
+//
+//    @ApiOperation("标记冻结")
+//    @PostMapping("markFreeze")
+//    public Result markFreeze(Long [] ids,Integer isFreeze) {
+//        if (ids == null || ids.length == 0) {
+//            return Result.error("参数错误");
+//        }
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper();
+//        update.in(UserEntity::getId,Arrays.asList(ids));
+//        update.set(UserEntity::getIsFreeze,isFreeze);
+//        userService.update(update);
+//        if(Integer.valueOf(0).equals(isFreeze)) {
+//            userService.updateLastFollowUpTime(Arrays.asList(ids));
+//        }
+//        return Result.ok();
+//    }
+//
+//
+//    @ApiOperation("删除人员数据")
+//    @PostMapping("deleteById")
+//    public Result deleteById(Long id) {
+//        if (id == null) {
+//            return Result.error("参数错误");
+//        }
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper();
+//        update.eq(UserEntity::getId,id);
+//        update.set(UserEntity::getIsDelete,1);
+//        userService.update(update);
+//        return Result.ok();
+//    }
+//
+//    @ApiOperation("删除人员数据")
+//    @PostMapping("updateRealName")
+//    public Result deleteById(Long id,String realName) {
+//        if (id == null) {
+//            return Result.error("参数错误");
+//        }
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper();
+//        update.eq(UserEntity::getId,id);
+//        update.set(UserEntity::getRealName,realName);
+//        userService.update(update);
+//        return Result.ok();
+//    }
+//
+//
+//    @ApiOperation("启用禁用员工")
+//    @PostMapping("enable")
+//    public Result setEnable(Long [] ids,Boolean enable) {
+//        if (ids == null || ids.length == 0) {
+//            return Result.error("参数错误");
+//        }
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper();
+//        update.in(UserEntity::getId,Arrays.asList(ids));
+//        update.set(UserEntity::getEnabled,enable);
+//        Boolean re =  userService.update(update);
+//        if (re) {
+//            return Result.ok();
+//        } else {
+//            return Result.error("操作失败");
+//        }
+//    }
+//
+//
+//    @ApiOperation("根据ids查询用户")
+//    @PostMapping("queryByIds")
+//    public Result queryByIds(Long [] ids) {
+//        if (ids == null || ids.length == 0) {
+//            return Result.error("参数错误");
+//        }
+//        LambdaUpdateWrapper<UserEntity> query = new LambdaUpdateWrapper();
+//        query.in(UserEntity::getId,Arrays.asList(ids));
+//        List<UserEntity> list  =  userService.list(query);
+//        return Result.ok(list);
+//    }
+//
+//
+//    @ApiOperation("同步OA数据")
+//    @PostMapping("syncOa")
+//    public Result syncOa() {
+//       userService.syncOa();
+//       return Result.ok();
+//    }
+//
+//    @ApiOperation("重置密码")
+//    @PostMapping("resetPassword")
+//    public Result resetPassword(Long userId) {
+//        if  (Objects.isNull(userId)) {
+//            return Result.error("参数错误");
+//        }
+//        String defaultPassWord = "storlead123456";
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper<UserEntity>();
+//        update.eq(UserEntity::getId,userId);
+//        update.set(UserEntity::getPassword,passwordEncoder.encode(defaultPassWord));
+//        userService.update(update);
+//        return Result.ok();
+//    }
+//
+//    @ApiOperation("修改用户信息")
+//    @PostMapping("updateUserInfo")
+//    public Result setPhone(SetUserDetailDTO dto) {
+//        Long userId = LoginUserUtil.getCurrentUserId();
+//        if  (Objects.isNull(userId)) {
+//            return Result.error("您未登录");
+//        }
+//        if  (StrUtil.isBlank(dto.getAvatar())) {
+//            return Result.error("参数错误,头像url不能为空");
+//        }
+//        if  (StrUtil.isBlank(dto.getMobile())) {
+//            return Result.error("参数错误,手机号不能为空");
+//        }
+//        UserEntity entity = userService.getById(userId);
+//        if (Objects.isNull(entity)) {
+//            return Result.error("未找到当前用户,请重新登录");
+//        }
+//        UserEntity oUser = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getMobile,dto.getMobile()).eq(UserEntity::getIsDelete,0).last("limit 1"));
+//        if (Objects.nonNull(oUser)) {
+//            if (!oUser.getId().equals(userId)) {
+//                return Result.error("该手机'"+dto.getMobile()+"'号已被占用!");
+//            }
+//        }
+//        if  (StrUtil.isNotBlank(dto.getEmail())) {
+//            oUser = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getMobile,dto.getEmail()).eq(UserEntity::getIsDelete,0).last("limit 1"));
+//            if (Objects.nonNull(oUser)) {
+//                if (!oUser.getId().equals(userId)) {
+//                    return Result.error("该邮箱'"+dto.getEmail()+"'已被占用!");
+//                }
+//            }
+//        }
+//        LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper<>();
+//        update.eq(UserEntity::getId, userId);
+//
+//        update.set(UserEntity::getAvatar, dto.getAvatar())
+//              .set(UserEntity::getEmail, dto.getEmail())
+//              .set(UserEntity::getNickName, dto.getNickName())
+//              .set(UserEntity::getRealName, dto.getRealName())
+//              .set(UserEntity::getMobile, dto.getMobile())
+//              .set(UserEntity::getSex, dto.getSex())
+//              .set(UserEntity::getBirthday, dto.getBirthday());
+//
+//        if (StrUtil.isNotBlank(dto.getJobDes())) {
+//            update.set(UserEntity::getJobDes, dto.getJobDes());
+//        }
+//
+//        try {
+//            boolean result = userService.update(update);
+//            if (!result) {
+//                return Result.error("更新用户信息失败,请重试。");
+//            }
+//        } catch (Exception e) {
+//            log.error("更新用户信息发生错误: {}", e.getMessage());
+//            return Result.error("系统错误,更新用户信息失败。");
+//        }
+//
+//        if (StrUtil.isNotBlank(dto.getDeptJobDes()) && Objects.nonNull(entity.getDeptId())) {
+//            DeptEntity dept = departService.getById(entity.getDeptId());
+//            if (!dto.getDeptJobDes().equals(dept.getDeptJobDes())) {
+//                if (Integer.valueOf(0).equals(entity.getIsLeader())) {
+//                    return Result.error("只有领导才能设置部门职责");
+//                }
+//                LambdaUpdateWrapper<DeptEntity> dUpdate = new LambdaUpdateWrapper<DeptEntity>();
+//                dUpdate.eq(DeptEntity::getId,entity.getDeptId());
+//                dUpdate.set(DeptEntity::getDeptJobDes,dto.getDeptJobDes());
+//                departService.update(dUpdate);
+//            }
+//        }
+//        return Result.ok();
+//    }
+//
+//    @ApiOperation("获取用户基础信息")
+//    @PostMapping("getSimpleUserInfo")
+//    @ApiResponses({
+//            @ApiResponse(code = 200, message = "", response = SetUserDetailVo.class)
+//    })
+//    public Result getSimpleUserInfo() {
+//        Long userId = LoginUserUtil.getCurrentUserId();
+//        if  (Objects.isNull(userId)) {
+//            return Result.error("您未登录");
+//        }
+//        UserVo entity = userService.getUserInfoById(userId);
+//
+//        SetUserDetailVo detailVo = new SetUserDetailVo();
+//        detailVo.setDeptId(entity.getDeptId());
+//        detailVo.setId(entity.getId());
+//        detailVo.setDeptName(entity.getDeptName());
+//        detailVo.setAvatar(entity.getAvatar());
+//        detailVo.setJobId(entity.getJobId());
+//        detailVo.setJobName(entity.getJobName());
+//        detailVo.setEmail(entity.getEmail());
+//        detailVo.setMobile(entity.getMobile());
+//        detailVo.setUserName(entity.getRealName());
+//        detailVo.setJobDes(entity.getJobDes());
+//        detailVo.setIsLeader(entity.getIsLeader());
+//        DeptEntity dept = departService.getById(entity.getDeptId());
+//        if (Objects.nonNull(dept)) {
+//            detailVo.setDeptJobDes(dept.getDeptJobDes());
+//        }
+//        return Result.ok(detailVo);
+//    }
+//
+//    public void updateManagerId(UserEntity user,Long oldManagerId){
+//        if (Objects.isNull(user)) {
+//            return;
+//        }
+//        if (Objects.isNull(user.getManagerId())) {
+//            return;
+//        }
+//        List<UserEntity> userEntities = userService.list(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getManagerId,user.getId()));
+//        for (UserEntity userEntity : userEntities) {
+//            if (StrUtil.isNotBlank(userEntity.getManagers())) {
+//                String routeCodeStr = ","+userEntity.getManagers()+",";
+//                routeCodeStr = routeCodeStr.replace(","+oldManagerId+",",","+userEntity.getManagerId()+",");
+//                StringUtils.startsWithIgnoreCase(routeCodeStr,",");
+//                StringUtils.endsWithIgnoreCase(routeCodeStr,",");
+//
+//                LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper();
+//                updateWrapper.eq(UserEntity::getId,userEntity.getId());
+//                updateWrapper.set(UserEntity::getManagers,routeCodeStr);
+//                userService.update(updateWrapper);
+//            }
+//        }
+//
+//    }
+//}

+ 124 - 0
storlead-centre-api/src/main/java/com/storlead/centre/system/UserController.java

@@ -0,0 +1,124 @@
+package com.storlead.centre.system;
+
+import com.storlead.framework.auth.vo.LoginUser;
+import com.storlead.framework.util.LoginUserUtil;
+import com.storlead.framework.web.assemble.Result;
+import com.storlead.user.model.UserInfo;
+import com.storlead.user.model.UserQueryModel;
+import com.storlead.user.pojo.entity.UserEntity;
+import com.storlead.user.pojo.vo.WxUserVO;
+import com.storlead.user.service.IUserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 用户表 前端控制器
+ * </p>
+ *
+ * @Author scott
+ * @since 2018-12-20
+ */
+@Slf4j
+@RestController
+@RequestMapping("/lingcun/user")
+@Api(tags="5.公共接口")
+public class UserController {
+
+	@Autowired
+	private IUserService sysUserService;
+
+	/**
+	 * 查询数据 查出所有部门,并以树结构数据格式响应给前端
+	 *
+	 * @return
+	 */
+	@RequestMapping(value = "/list", method = RequestMethod.GET)
+	@ApiOperation(value = "公共接口-用户信息-列表", notes = "公共接口-用户信息-列表")
+	@ApiResponses({
+			@ApiResponse(code = 200, message = "", response = UserInfo.class)
+	})
+	public Result<List<UserInfo>> queryTreeList(UserQueryModel userQueryModel) {
+		Result<List<UserInfo>> result = new Result<>();
+		try {
+			List<UserInfo> list = sysUserService.getUserListBySearch(userQueryModel);
+			result.setResult(list);
+			result.setSuccess(true);
+		} catch (Exception e) {
+			log.error(e.getMessage(),e);
+		}
+		return result;
+	}
+
+	 /***
+	  * @Description: 用户列表,按拼音首字母排序
+	  * @Param:
+	  * @return:
+	  * @Author: YPZ
+	  * @Date: 2023/3/16 11:54
+	  */
+	@RequestMapping(value = "/user-list-pinyin", method = RequestMethod.GET)
+	@ApiOperation(value = "公共接口-用户信息-列表(按拼音首字母排序)", notes = "公共接口-用户信息-列表(按拼音首字母排序)")
+	@ApiResponses({
+			@ApiResponse(code = 200, message = "", response = UserInfo.class)
+	})
+	public Result<List<WxUserVO>> userListPinyin(UserQueryModel userQueryModel) {
+		Result<List<WxUserVO>> result = new Result<>();
+		try {
+			List<WxUserVO> wxUserInfoList =sysUserService.getPingyinUserList(userQueryModel);
+			result.setResult(wxUserInfoList);
+			result.setSuccess(true);
+		} catch (Exception e) {
+			log.error(e.getMessage(),e);
+		}
+		return result;
+	}
+
+	@RequestMapping(value = "/list-subordinate", method = RequestMethod.GET)
+	@ApiOperation(value = "公共接口-下级用户信息-列表", notes = "公共接口-下级用户信息-列表")
+	@ApiResponses({
+			@ApiResponse(code = 200, message = "", response = UserInfo.class)
+	})
+	public Result<List<UserInfo>> listSubordinate(UserQueryModel userQueryModel) {
+		Result<List<UserInfo>> result = new Result<>();
+		try {
+			LoginUser loginUser = LoginUserUtil.getLoginUser();
+			List<UserInfo> list = sysUserService.getUserListBySearch(userQueryModel);
+			List<Long> allSubordinate = sysUserService.getAllSubordinate(loginUser.getId());
+			Set<Long> allSubordinateSet =new HashSet<>(allSubordinate);
+			list = list.stream().filter((u)->allSubordinateSet.contains(u.getId())).collect(Collectors.toList());
+			result.setResult(list);
+			result.setSuccess(true);
+		} catch (Exception e) {
+			log.error(e.getMessage(),e);
+		}
+		return result;
+	}
+
+	/**
+	 * 查询数据 查出所有部门,并以树结构数据格式响应给前端
+	 *
+	 * @return
+	 */
+	@GetMapping(value = "/findManager")
+	@ApiOperation(value = "公共接口-用户信息-查看当前用户领导", notes = "公共接口-用户信息-查看当前用户领导")
+	public Result findManager() {
+		LoginUser loginUser = LoginUserUtil.getLoginUser();
+		UserEntity user = sysUserService.getById(loginUser.getManagerId());
+		return Result.ok(user);
+	}
+
+}

+ 10 - 6
storlead-dependencies/pom.xml

@@ -90,11 +90,11 @@
                 <version>${revision}</version>
             </dependency>
 
-<!--            <dependency>-->
-<!--                <groupId>com.storlead.boot</groupId>-->
-<!--                <artifactId>storlead-framework</artifactId>-->
-<!--                <version>${revision}</version>-->
-<!--            </dependency>-->
+            <dependency>
+                <groupId>com.storlead.boot</groupId>
+                <artifactId>storlead-user</artifactId>
+                <version>${revision}</version>
+            </dependency>
 
             <dependency>
                 <groupId>com.storlead.boot</groupId>
@@ -102,7 +102,11 @@
                 <version>${revision}</version>
             </dependency>
 
-
+            <dependency>
+                <groupId>com.storlead.boot</groupId>
+                <artifactId>storlead-sms</artifactId>
+                <version>${revision}</version>
+            </dependency>
 
             <dependency>
                 <groupId>com.storlead.boot</groupId>

+ 152 - 0
storlead-framework/storlead-auth/src/main/java/com/storlead/framework/auth/vo/LoginUser.java

@@ -1,10 +1,16 @@
 package com.storlead.framework.auth.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Set;
 
 /**
  * @program: storlead-storlead-centre-platform
@@ -26,4 +32,150 @@ public class LoginUser implements Serializable {
      * 登录人账号
      */
     private String userName;
+
+    /**
+     * 公司ID
+     */
+    private Long companyId;
+
+    /**
+     * 分公司ID
+     */
+    private Long subCompanyId;
+
+    /**
+     * 部门ID
+     */
+    private Long deptId;
+
+    /**
+     * 部门ID
+     */
+    private String deptName;
+
+    /**
+     * 职位ID
+     */
+    private Long jobId;
+
+    /**
+     * 职位ID
+     */
+    private String jobName;
+
+    /**
+     * 测试
+     */
+    private Integer test;
+
+    /**
+     * 角色类型
+     */
+//    private UserRoleType roleType;
+
+    /**
+     * 登录人名字
+     */
+    private String realName;
+
+    /**
+     * 登录人密码
+     */
+    private String password;
+    /**
+     * 企业微信userid
+     */
+    private String xworkUserId;
+
+    /**
+     * 登录人名字
+     */
+    private String nickName;
+
+    /**
+     * 头像
+     */
+    private String avatar;
+
+    /**
+     * 生日
+     */
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern="yyyy-MM-dd")
+    private LocalDate birthday;
+
+    /**
+     * 性别(1:男 2:女)
+     */
+    private String sex;
+
+    /**
+     * 电子邮件
+     */
+    private String email;
+
+    /**
+     * 电话
+     */
+    private String phone;
+
+    private String mobile;
+
+    /**
+     * 状态(1:正常 0:冻结 )
+     */
+    private Integer enabled;
+
+
+    /**
+     * 是否领导:0、否;1、分公司领导;2、部门领导
+     */
+    private Integer isLeader;
+
+    private String dataScope;
+
+    @ApiModelProperty(value = "直接上级ID")
+    private Long managerId;
+
+    @ApiModelProperty(value = "领导人ID集合")
+    private String managers;
+
+    /**
+     * 部门路由
+     */
+    private String deptCode;
+
+    @ApiModelProperty(value = "是否是超管")
+    private Boolean isAdmin;
+
+    /**
+     * 所属子公司路由
+     */
+    private String subCompanyCode;
+
+    /**
+     * 所属公司路由
+     */
+    private String companyCode;
+
+    @ApiModelProperty(value = "部门岗位职责")
+    private String deptJobDes;
+
+    @ApiModelProperty(value = "岗位职责")
+    private String jobDes;
+
+    private Set<Long> roleIds;
+
+    private String apiUrl;
+
+    private String scopeMenuId;
+
+    private Integer commonScope;
+
+    private String commonScopeType;
+    /**
+     * 按钮权限code
+     */
+    private Set<String> btnRes;
+
 }

+ 6 - 0
storlead-framework/storlead-common/pom.xml

@@ -46,6 +46,12 @@
             <artifactId>java-jwt</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+
         <!--  jwt 需要,移除会报错  -->
         <dependency>
             <groupId>io.jsonwebtoken</groupId>

+ 2 - 2
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/constant/CommonConstant.java

@@ -20,12 +20,12 @@ public interface CommonConstant {
 	/**
 	 * 真
 	 */
-	Integer FALSE_FLAG = 0;
+	Integer DEL_FLAG_0 = 0;
 
     /**
      * 假
      */
-    Integer TRUE_FLAG = 1;
+    Integer DEL_FLAG_1 = 1;
 
 
 	/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */

+ 25 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/constant/RedisKeySaltConstant.java

@@ -0,0 +1,25 @@
+package com.storlead.framework.common.constant;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-07-05 09:20
+ */
+public class RedisKeySaltConstant {
+    /**
+     * 操作成功
+     */
+    public static final String API_CODE_REDIS = "api_code_redis_key_";
+
+    /**
+     * 操作成功
+     */
+    public static final String REDIS_API_CODE_SERVICE_CODE_KEY = "api_code_redis_key_user_service_code";
+
+
+    /**
+     * 操作成功
+     */
+    public static final String REDIS_LOGIN_VALID_CODE_KEY = "redis_login_valid_code_key_";
+}

+ 86 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/properties/UrlChainDefinitionPorperties.java

@@ -0,0 +1,86 @@
+package com.storlead.framework.common.properties;
+
+import lombok.Data;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-07-04 16:16
+ */
+@Data
+@Configuration
+public class UrlChainDefinitionPorperties {
+    private String contextPath = "/api" ;
+	private String [] authWhitelist = {
+			"/",
+			"/lingcun/common/view/**",
+			"/lingcun/common/download/**",
+			"/lingcun/common/pdf/**",
+			"/generic/**",
+			"/doc.html",
+			"/**/*.js",
+			"/**/*.css",
+			"/**/*.html",
+			"/**/*.svg",
+			"/**/*.pdf",
+			"/**/*.jpg",
+			"/**/*.png",
+			"/**/*.ico",
+			"/actuator/health",
+			"/actuator/**",
+			"/app/**",
+			"/h5/**",
+			"/**/*.ttf",
+			"/**/*.woff",
+			"/druid/**",
+			"/swagger-ui.html",
+			"/**/swagger-ui",
+			"/swagger**/**",
+			"/webjars/**",
+			"/v2/**",
+			"/xwork/**",
+			"/lingcun/getPhoneCode",
+			"/lingcun/loginByMobile",
+			"/lingcun/login",
+			"/sys/auth/external_login",
+			"/lingcun/phone-login",
+			"/sys/auth/login",
+			"/sys/auth/redirect",
+			"/actuator/metrics/**",
+			"/actuator/httptrace/**",
+			"/actuator/redis/**",
+			"/sys/common/403",
+			"/sys/common/403",
+			"/reward/resource",
+			"/xwork/login",
+			"/xwork/code-login",
+			"/view/thumbnail",
+			"/sys/custom/settings/get",
+			"/tenant/license/getLicenseCode",
+			"/analysis-report/edit",
+			"/gpt/chatWebSocket/**",
+			"/sys/user/exchangeToken",
+			"/sys/menu/allMenulist",
+			"/sys/dict/pageDict",
+			"/mail/bind_mail_customer_all",
+			"/mail/bind_mail_customer",
+			"/sys/menu/update_menu_icon",
+			"/mail/file/images",
+			"/mail/file/cache_image_file",
+			"/mail/import_mail_eml",
+			"/mail/import_mail_eml_zip",
+			"/sys/test/receive_mail_test",
+			"/mail/list.json",
+			"/mail/listUrl",
+			"/mail/v1/file/content",
+			"/ram/oss/get_post_signature_for_oss_upload",
+			"/sys/permission/getUserAccessResourceTest",
+			"/mail/draft_download_url",
+			"/mail/download_url",
+			"/wxapi/wxclientmenu/**",
+			"/wxapi/wxclientmenu/*",
+			"/wxapi/getauth"
+	};
+}

+ 47 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/util/UrlChainBlackAndWhiteUtil.java

@@ -0,0 +1,47 @@
+package com.storlead.framework.common.util;
+
+import com.storlead.framework.common.properties.UrlChainDefinitionPorperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-07-04 16:24
+ */
+@Component
+public class UrlChainBlackAndWhiteUtil {
+    @Autowired
+    private UrlChainDefinitionPorperties properties;
+
+    public String getContextPath() {
+        return properties.getContextPath();
+    }
+
+    /**
+     * 白名单URL
+     * @param uri
+     * @return
+     */
+    public boolean IsWhiteUri(String uri)
+    {
+        String [] AUTH_WHITELIST = properties.getAuthWhitelist();
+        uri = uri.replace(properties.getContextPath()+"/","/");
+        for (int i = 0; i < AUTH_WHITELIST.length; i++)
+        {
+            if (AUTH_WHITELIST[i].length() > 0)
+            {
+                String whiteuri = AUTH_WHITELIST[i];
+                whiteuri = whiteuri.trim();
+                AntPathMatcher antPathMatcher = new AntPathMatcher();
+                boolean match = antPathMatcher.match(whiteuri,uri);
+                if (match) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

+ 6 - 6
storlead-framework/storlead-mybatis/src/main/java/com/storlead/framework/mybatis/service/impl/MyBaseServiceImpl.java

@@ -30,7 +30,7 @@ public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField
         }
         UpdateWrapper updateWrapper = new UpdateWrapper<>();
         updateWrapper.eq("id",id);
-        updateWrapper.set("is_delete", CommonConstant.TRUE_FLAG);
+        updateWrapper.set("is_delete", CommonConstant.DEL_FLAG_1);
         return this.update(updateWrapper);
     }
 
@@ -41,7 +41,7 @@ public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField
         }
         UpdateWrapper updateWrapper = new UpdateWrapper<>();
         updateWrapper.in("id",ids);
-        updateWrapper.set("is_delete", CommonConstant.TRUE_FLAG);
+        updateWrapper.set("is_delete", CommonConstant.DEL_FLAG_1);
         return this.update(updateWrapper);
     }
 
@@ -62,7 +62,7 @@ public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField
         }
         UpdateWrapper updateWrapper = new UpdateWrapper<>();
         updateWrapper.in("id",ids);
-        updateWrapper.set("enable", CommonConstant.TRUE_FLAG);
+        updateWrapper.set("enable", CommonConstant.DEL_FLAG_1);
         return this.update(updateWrapper);
     }
 
@@ -73,7 +73,7 @@ public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField
         }
         UpdateWrapper updateWrapper = new UpdateWrapper<>();
         updateWrapper.eq("id",id);
-        updateWrapper.set("enable", CommonConstant.TRUE_FLAG);
+        updateWrapper.set("enable", CommonConstant.DEL_FLAG_1);
         return this.update(updateWrapper);
     }
 
@@ -84,7 +84,7 @@ public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField
         }
         UpdateWrapper updateWrapper = new UpdateWrapper<>();
         updateWrapper.eq("id",ids);
-        updateWrapper.set("enable", CommonConstant.FALSE_FLAG);
+        updateWrapper.set("enable", CommonConstant.DEL_FLAG_0);
         return this.update(updateWrapper);
     }
 
@@ -95,7 +95,7 @@ public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField
         }
         UpdateWrapper updateWrapper = new UpdateWrapper<>();
         updateWrapper.eq("id",id);
-        updateWrapper.set("enable", CommonConstant.FALSE_FLAG);
+        updateWrapper.set("enable", CommonConstant.DEL_FLAG_0);
         return this.update(updateWrapper);
     }
 }

+ 35 - 35
storlead-framework/storlead-redis/src/main/java/com/storlead/framework/redis/config/RedissonConfig.java

@@ -1,35 +1,35 @@
-//package com.storlead.framework.redis.config;
-//
-//import org.redisson.Redisson;
-//import org.redisson.api.RedissonClient;
-//import org.redisson.config.Config;
-//import org.springframework.beans.factory.annotation.Value;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//
-///**
-// * @program: sp-sales
-// * @description:
-// * @author: chenkq
-// * @create: 2022-08-08 11:39
-// */
-//@Configuration
-//public class RedissonConfig {
-//
-//    @Value("${spring.redis.host}")
-//    private String host;
-//
-//    @Value("${spring.redis.port}")
-//    private String port;
-//
-//    @Value("${spring.redis.password}")
-//    private String password;
-//
-//    @Bean
-//    public RedissonClient getRedisson() {
-//        Config config = new Config();
-//        config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
-//        RedissonClient redissonClient = Redisson.create(config);
-//        return redissonClient;
-//    }
-//}
+package com.storlead.framework.redis.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-08-08 11:39
+ */
+@Configuration
+public class RedissonConfig {
+
+    @Value("${spring.redis.host}")
+    private String host;
+
+    @Value("${spring.redis.port}")
+    private String port;
+
+    @Value("${spring.redis.password}")
+    private String password;
+
+    @Bean
+    public RedissonClient getRedisson() {
+        Config config = new Config();
+        config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
+        RedissonClient redissonClient = Redisson.create(config);
+        return redissonClient;
+    }
+}

+ 54 - 0
storlead-sms/pom.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.storlead.boot</groupId>
+        <artifactId>storlead-centre-platform</artifactId>
+        <version>1.0</version>
+    </parent>
+
+    <artifactId>storlead-sms</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-mybatis</artifactId>
+        </dependency>
+
+        <!--阿里短信 SDK start -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.4.9</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-dysmsapi -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+            <version>2.1.0</version>
+        </dependency>
+
+
+    </dependencies>
+
+</project>

+ 37 - 0
storlead-sms/src/main/java/com/storlead/sms/constants/SmsTemplateConstants.java

@@ -0,0 +1,37 @@
+package com.storlead.sms.constants;
+
+import com.storlead.framework.common.util.encryptor.AccessKeyEncryptor;
+
+/**
+ * 短信模板常量类
+ * ˚
+ *
+ * @author blank
+ * @since 2018/5/17 下午3:02
+ */
+public class SmsTemplateConstants {
+
+    /**
+     * 阿里短信KeyId
+     * LTAINcIoMlgLFqYA
+     */
+    public final static String SMS_ACCESS_KEY = AccessKeyEncryptor.getAccessKeyEncryptor("").decrypt("oR84iMcKamMRyLUYSK9oT6RtfW6g8/J/Z7SZl6bSpa0=");
+
+    /**
+     * 阿里短信密钥
+     * IEOhX7cztq1Iakb9eUmBcSLjU2mpZf
+     */
+    public static String SMS_ACCESS_KEY_SECRET = "8XFM6wbjkLqkhO5BSD3FcbD7EviWv9";
+
+    /**
+     * 阿里短信 验证码模板
+     * SMS_70175033
+     */
+    public static String SMS_CHECK_CODE_TEMPLATE = "SMS_70175033";
+
+    /**
+     * 单用户当日最大次数
+     */
+    public static Integer SEND_MAXIMIZE  = 10;
+
+}

+ 47 - 0
storlead-sms/src/main/java/com/storlead/sms/controller/SmsLogApiController.java

@@ -0,0 +1,47 @@
+package com.storlead.sms.controller;//package com.storlead.sms.controller;
+//
+//import cn.hutool.core.util.StrUtil;
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.storlead.frame.core.assemble.Result;
+//import com.storlead.sms.service.SmsLogService;
+//import io.swagger.annotations.Api;
+//import io.swagger.annotations.ApiOperation;
+//import org.springframework.web.bind.annotation.PostMapping;
+//import org.springframework.web.bind.annotation.RequestMapping;
+//import org.springframework.web.bind.annotation.RestController;
+//
+//import javax.annotation.Resource;
+//
+///**
+// * @program: sp-cloud
+// * @description: 短信发送
+// * @author: chenkq
+// * @create: 2022-05-27 10:08
+// */
+//
+//
+//@Api(tags = "系统: 企业微信管理")
+//@RestController
+//@RequestMapping("/sys/sms")
+//public class SmsLogApiController {
+//
+//    @Resource
+//    private SmsLogService smsLogService;
+//
+//    @ApiOperation("获取AccessToken")
+//    @PostMapping("/sendLoginVerifyCode")
+//    public Result sendLoginVerifyCode(String mobile) {
+//        if (StrUtil.isBlank(mobile)) {
+//            return Result.error("参数错误");
+//        }
+//        //UserEn userAccount = userAccountService.getOne(new LambdaQueryWrapper<UserAccount>().eq(UserAccount::getAccount,mobile));
+////      if (userAccount == null) {
+////          return Result.error("手机号错误,该手机号用户不存在");
+////      }
+//        try {
+//            return  smsLogService.sendLoginSmsCode(mobile);
+//        }catch (Exception e) {
+//            return  Result.error(e.getMessage());
+//        }
+//    }
+//}

+ 452 - 0
storlead-sms/src/main/java/com/storlead/sms/exception/SMSException.java

@@ -0,0 +1,452 @@
+package com.storlead.sms.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.PrivilegedActionException;
+
+/**
+ * 短信异常类
+ *
+ * @author blank
+ * @since 2018/6/29 上午10:37
+ */
+public class SMSException extends Exception {
+    /**
+     * Constructs a new exception with {@code null} as its detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     */
+    public SMSException() {
+        super();
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message.  The
+     * cause is not initialized, and may subsequently be initialized by
+     * a call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public SMSException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A <tt>null</tt> value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public SMSException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified cause and a detail
+     * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+     * typically contains the class and detail message of <tt>cause</tt>).
+     * This constructor is useful for exceptions that are little more than
+     * wrappers for other throwables (for example, {@link
+     * PrivilegedActionException}).
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A <tt>null</tt> value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public SMSException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message,
+     * cause, suppression enabled or disabled, and writable stack
+     * trace enabled or disabled.
+     *
+     * @param message            the detail message.
+     * @param cause              the cause.  (A {@code null} value is permitted,
+     *                           and indicates that the cause is nonexistent or unknown.)
+     * @param enableSuppression  whether or not suppression is enabled
+     *                           or disabled
+     * @param writableStackTrace whether or not the stack trace should
+     *                           be writable
+     * @since 1.7
+     */
+    protected SMSException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+
+    /**
+     * Returns the detail message string of this throwable.
+     *
+     * @return the detail message string of this {@code Throwable} instance
+     * (which may be {@code null}).
+     */
+    @Override
+    public String getMessage() {
+        return super.getMessage();
+    }
+
+    /**
+     * Creates a localized description of this throwable.
+     * Subclasses may override this method in order to produce a
+     * locale-specific message.  For subclasses that do not override this
+     * method, the default implementation returns the same result as
+     * {@code getMessage()}.
+     *
+     * @return The localized description of this throwable.
+     * @since JDK1.1
+     */
+    @Override
+    public String getLocalizedMessage() {
+        return super.getLocalizedMessage();
+    }
+
+    /**
+     * Returns the cause of this throwable or {@code null} if the
+     * cause is nonexistent or unknown.  (The cause is the throwable that
+     * caused this throwable to get thrown.)
+     *
+     * <p>This implementation returns the cause that was supplied via one of
+     * the constructors requiring a {@code Throwable}, or that was set after
+     * creation with the {@link #initCause(Throwable)} method.  While it is
+     * typically unnecessary to override this method, a subclass can override
+     * it to return a cause set by some other means.  This is appropriate for
+     * a "legacy chained throwable" that predates the addition of chained
+     * exceptions to {@code Throwable}.  Note that it is <i>not</i>
+     * necessary to override any of the {@code PrintStackTrace} methods,
+     * all of which invoke the {@code getCause} method to determine the
+     * cause of a throwable.
+     *
+     * @return the cause of this throwable or {@code null} if the
+     * cause is nonexistent or unknown.
+     * @since 1.4
+     */
+    @Override
+    public synchronized Throwable getCause() {
+        return super.getCause();
+    }
+
+    /**
+     * Initializes the <i>cause</i> of this throwable to the specified value.
+     * (The cause is the throwable that caused this throwable to get thrown.)
+     *
+     * <p>This method can be called at most once.  It is generally called from
+     * within the constructor, or immediately after creating the
+     * throwable.  If this throwable was created
+     * with  or
+     * , this method cannot be called
+     * even once.
+     *
+     * <p>An example of using this method on a legacy throwable type
+     * without other support for setting the cause is:
+     *
+     * <pre>
+     * try {
+     *     lowLevelOp();
+     * } catch (LowLevelException le) {
+     *     throw (HighLevelException)
+     *           new HighLevelException().initCause(le); // Legacy constructor
+     * }
+     * </pre>
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @return a reference to this {@code Throwable} instance.
+     * @throws IllegalArgumentException if {@code cause} is this
+     *                                  throwable.  (A throwable cannot be its own cause.)
+     * @throws IllegalStateException    if this throwable was
+     *                                  created with  or
+     *                                  , or this method has already
+     *                                  been called on this throwable.
+     * @since 1.4
+     */
+    @Override
+    public synchronized Throwable initCause(Throwable cause) {
+        return super.initCause(cause);
+    }
+
+    /**
+     * Returns a short description of this throwable.
+     * The result is the concatenation of:
+     * <ul>
+     * <li> the {@linkplain Class#getName() name} of the class of this object
+     * <li> ": " (a colon and a space)
+     * <li> the result of invoking this object's {@link #getLocalizedMessage}
+     * method
+     * </ul>
+     * If {@code getLocalizedMessage} returns {@code null}, then just
+     * the class name is returned.
+     *
+     * @return a string representation of this throwable.
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+    /**
+     * Prints this throwable and its backtrace to the
+     * standard error stream. This method prints a stack trace for this
+     * {@code Throwable} object on the error output stream that is
+     * the value of the field {@code System.err}. The first line of
+     * output contains the result of the {@link #toString()} method for
+     * this object.  Remaining lines represent data previously recorded by
+     * the method {@link #fillInStackTrace()}. The format of this
+     * information depends on the implementation, but the following
+     * example may be regarded as typical:
+     * <blockquote><pre>
+     * java.lang.NullPointerException
+     *         at MyClass.mash(MyClass.java:9)
+     *         at MyClass.crunch(MyClass.java:6)
+     *         at MyClass.main(MyClass.java:3)
+     * </pre></blockquote>
+     * This example was produced by running the program:
+     * <pre>
+     * class MyClass {
+     *     public static void main(String[] args) {
+     *         crunch(null);
+     *     }
+     *     static void crunch(int[] a) {
+     *         mash(a);
+     *     }
+     *     static void mash(int[] b) {
+     *         System.out.println(b[0]);
+     *     }
+     * }
+     * </pre>
+     * The backtrace for a throwable with an initialized, non-null cause
+     * should generally include the backtrace for the cause.  The format
+     * of this information depends on the implementation, but the following
+     * example may be regarded as typical:
+     * <pre>
+     * HighLevelException: MidLevelException: LowLevelException
+     *         at Junk.a(Junk.java:13)
+     *         at Junk.main(Junk.java:4)
+     * Caused by: MidLevelException: LowLevelException
+     *         at Junk.c(Junk.java:23)
+     *         at Junk.b(Junk.java:17)
+     *         at Junk.a(Junk.java:11)
+     *         ... 1 more
+     * Caused by: LowLevelException
+     *         at Junk.e(Junk.java:30)
+     *         at Junk.d(Junk.java:27)
+     *         at Junk.c(Junk.java:21)
+     *         ... 3 more
+     * </pre>
+     * Note the presence of lines containing the characters {@code "..."}.
+     * These lines indicate that the remainder of the stack trace for this
+     * exception matches the indicated number of frames from the bottom of the
+     * stack trace of the exception that was caused by this exception (the
+     * "enclosing" exception).  This shorthand can greatly reduce the length
+     * of the output in the common case where a wrapped exception is thrown
+     * from same method as the "causative exception" is caught.  The above
+     * example was produced by running the program:
+     * <pre>
+     * public class Junk {
+     *     public static void main(String args[]) {
+     *         try {
+     *             a();
+     *         } catch(HighLevelException e) {
+     *             e.printStackTrace();
+     *         }
+     *     }
+     *     static void a() throws HighLevelException {
+     *         try {
+     *             b();
+     *         } catch(MidLevelException e) {
+     *             throw new HighLevelException(e);
+     *         }
+     *     }
+     *     static void b() throws MidLevelException {
+     *         c();
+     *     }
+     *     static void c() throws MidLevelException {
+     *         try {
+     *             d();
+     *         } catch(LowLevelException e) {
+     *             throw new MidLevelException(e);
+     *         }
+     *     }
+     *     static void d() throws LowLevelException {
+     *        e();
+     *     }
+     *     static void e() throws LowLevelException {
+     *         throw new LowLevelException();
+     *     }
+     * }
+     *
+     * class HighLevelException extends Exception {
+     *     HighLevelException(Throwable cause) { super(cause); }
+     * }
+     *
+     * class MidLevelException extends Exception {
+     *     MidLevelException(Throwable cause)  { super(cause); }
+     * }
+     *
+     * class LowLevelException extends Exception {
+     * }
+     * </pre>
+     * As of release 7, the platform supports the notion of
+     * <i>suppressed exceptions</i> (in conjunction with the {@code
+     * try}-with-resources statement). Any exceptions that were
+     * suppressed in order to deliver an exception are printed out
+     * beneath the stack trace.  The format of this information
+     * depends on the implementation, but the following example may be
+     * regarded as typical:
+     *
+     * <pre>
+     * Exception in thread "main" java.lang.Exception: Something happened
+     *  at Foo.bar(Foo.java:10)
+     *  at Foo.main(Foo.java:5)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 0
+     *          at Resource.close(Resource.java:26)
+     *          at Foo.bar(Foo.java:9)
+     *          ... 1 more
+     * </pre>
+     * Note that the "... n more" notation is used on suppressed exceptions
+     * just at it is used on causes. Unlike causes, suppressed exceptions are
+     * indented beyond their "containing exceptions."
+     *
+     * <p>An exception can have both a cause and one or more suppressed
+     * exceptions:
+     * <pre>
+     * Exception in thread "main" java.lang.Exception: Main block
+     *  at Foo3.main(Foo3.java:7)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 2
+     *          at Resource.close(Resource.java:26)
+     *          at Foo3.main(Foo3.java:5)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 1
+     *          at Resource.close(Resource.java:26)
+     *          at Foo3.main(Foo3.java:5)
+     * Caused by: java.lang.Exception: I did it
+     *  at Foo3.main(Foo3.java:8)
+     * </pre>
+     * Likewise, a suppressed exception can have a cause:
+     * <pre>
+     * Exception in thread "main" java.lang.Exception: Main block
+     *  at Foo4.main(Foo4.java:6)
+     *  Suppressed: Resource2$CloseFailException: Resource ID = 1
+     *          at Resource2.close(Resource2.java:20)
+     *          at Foo4.main(Foo4.java:5)
+     *  Caused by: java.lang.Exception: Rats, you caught me
+     *          at Resource2$CloseFailException.&lt;init&gt;(Resource2.java:45)
+     *          ... 2 more
+     * </pre>
+     */
+    @Override
+    public void printStackTrace() {
+        super.printStackTrace();
+    }
+
+    /**
+     * Prints this throwable and its backtrace to the specified print stream.
+     *
+     * @param s {@code PrintStream} to use for output
+     */
+    @Override
+    public void printStackTrace(PrintStream s) {
+        super.printStackTrace(s);
+    }
+
+    /**
+     * Prints this throwable and its backtrace to the specified
+     * print writer.
+     *
+     * @param s {@code PrintWriter} to use for output
+     * @since JDK1.1
+     */
+    @Override
+    public void printStackTrace(PrintWriter s) {
+        super.printStackTrace(s);
+    }
+
+    /**
+     * Fills in the execution stack trace. This method records within this
+     * {@code Throwable} object information about the current state of
+     * the stack frames for the current thread.
+     *
+     * <p>If the stack trace of this {@code Throwable} {@linkplain
+     * Throwable#Throwable(String, Throwable, boolean, boolean) is not
+     * writable}, calling this method has no effect.
+     *
+     * @return a reference to this {@code Throwable} instance.
+     * @see Throwable#printStackTrace()
+     */
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return super.fillInStackTrace();
+    }
+
+    /**
+     * Provides programmatic access to the stack trace information printed by
+     * {@link #printStackTrace()}.  Returns an array of stack trace elements,
+     * each representing one stack frame.  The zeroth element of the array
+     * (assuming the array's length is non-zero) represents the top of the
+     * stack, which is the last method invocation in the sequence.  Typically,
+     * this is the point at which this throwable was created and thrown.
+     * The last element of the array (assuming the array's length is non-zero)
+     * represents the bottom of the stack, which is the first method invocation
+     * in the sequence.
+     *
+     * <p>Some virtual machines may, under some circumstances, omit one
+     * or more stack frames from the stack trace.  In the extreme case,
+     * a virtual machine that has no stack trace information concerning
+     * this throwable is permitted to return a zero-length array from this
+     * method.  Generally speaking, the array returned by this method will
+     * contain one element for every frame that would be printed by
+     * {@code printStackTrace}.  Writes to the returned array do not
+     * affect future calls to this method.
+     *
+     * @return an array of stack trace elements representing the stack trace
+     * pertaining to this throwable.
+     * @since 1.4
+     */
+    @Override
+    public StackTraceElement[] getStackTrace() {
+        return super.getStackTrace();
+    }
+
+    /**
+     * Sets the stack trace elements that will be returned by
+     * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
+     * and related methods.
+     * <p>
+     * This method, which is designed for use by RPC frameworks and other
+     * advanced systems, allows the client to override the default
+     * stack trace that is either generated by {@link #fillInStackTrace()}
+     * when a throwable is constructed or deserialized when a throwable is
+     * read from a serialization stream.
+     *
+     * <p>If the stack trace of this {@code Throwable} {@linkplain
+     * Throwable#Throwable(String, Throwable, boolean, boolean) is not
+     * writable}, calling this method has no effect other than
+     * validating its argument.
+     *
+     * @param stackTrace the stack trace elements to be associated with
+     *                   this {@code Throwable}.  The specified array is copied by this
+     *                   call; changes in the specified array after the method invocation
+     *                   returns will have no affect on this {@code Throwable}'s stack
+     *                   trace.
+     * @throws NullPointerException if {@code stackTrace} is
+     *                              {@code null} or if any of the elements of
+     *                              {@code stackTrace} are {@code null}
+     * @since 1.4
+     */
+    @Override
+    public void setStackTrace(StackTraceElement[] stackTrace) {
+        super.setStackTrace(stackTrace);
+    }
+}

+ 16 - 0
storlead-sms/src/main/java/com/storlead/sms/mapper/SmsLogMapper.java

@@ -0,0 +1,16 @@
+package com.storlead.sms.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.sms.pojo.entity.SmsLogEntity;
+
+/**
+ * <p>
+ * 短信日志 Mapper 接口
+ * </p>
+ *
+ * @author chenkq
+ * @since 2022-05-27
+ */
+public interface SmsLogMapper extends BaseMapper<SmsLogEntity> {
+
+}

+ 73 - 0
storlead-sms/src/main/java/com/storlead/sms/pojo/entity/SmsLogEntity.java

@@ -0,0 +1,73 @@
+package com.storlead.sms.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * <p>
+ * 短信日志
+ * </p>
+ *
+ * @author chenkq
+ * @since 2022-05-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SmsLogEntity extends SysBaseField {
+
+    /**
+     * ID
+     */
+    private Long smsLogId;
+
+    /**
+     * 发送用户
+     */
+    private Long userId;
+
+    /**
+     * 发送账号
+     */
+    private String mobile;
+
+    /**
+     * 校验码
+     */
+    private String verifyCode;
+
+    /**+
+     * 短信内容
+     */
+    private String message;
+
+    /**
+     * 0:未发送,1:成功,2:失败
+     */
+    private Integer status;
+
+    /**
+     * 0:短信验证码
+     */
+    private Integer type;
+
+    /**
+     * 发送时间
+     */
+    private Date sendTime;
+
+    /**
+     * 有效时间(分钟)
+     */
+    private Integer validTime;
+
+    /**
+     * 是否使用
+     */
+    @TableField(exist = false)
+    private Boolean isUsed = false;
+
+}

+ 23 - 0
storlead-sms/src/main/java/com/storlead/sms/service/SmsLogService.java

@@ -0,0 +1,23 @@
+package com.storlead.sms.service;
+
+import com.aliyuncs.exceptions.ClientException;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.storlead.framework.web.assemble.Result;
+import com.storlead.sms.exception.SMSException;
+import com.storlead.sms.pojo.entity.SmsLogEntity;
+
+/**
+ * <p>
+ * 短信日志 服务类
+ * </p>
+ *
+ * @author chenkq
+ * @since 2022-05-27
+ */
+public interface SmsLogService extends IService<SmsLogEntity> {
+
+    /**
+     * 发送登录短信code
+     */
+    public Result sendLoginSmsCode(String mobile) throws ClientException, SMSException;
+}

+ 91 - 0
storlead-sms/src/main/java/com/storlead/sms/service/impl/SmsLogServiceImpl.java

@@ -0,0 +1,91 @@
+package com.storlead.sms.service.impl;
+
+import com.aliyuncs.exceptions.ClientException;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.storlead.framework.common.constant.RedisKeySaltConstant;
+import com.storlead.framework.common.util.RandomCodeUtil;
+import com.storlead.framework.redis.RedisService;
+import com.storlead.framework.web.assemble.Result;
+import com.storlead.framework.web.enums.ErrorMsgCode;
+import com.storlead.sms.constants.SmsTemplateConstants;
+import com.storlead.sms.exception.SMSException;
+import com.storlead.sms.mapper.SmsLogMapper;
+import com.storlead.sms.pojo.entity.SmsLogEntity;
+import com.storlead.sms.service.SmsLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * <p>
+ * 短信日志 服务实现类
+ * </p>
+ *
+ * @author chenkq
+ * @since 2022-05-27
+ */
+@Service
+public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLogEntity> implements SmsLogService {
+
+    @Autowired
+    private RedisService redisService;
+
+
+
+    @Override
+    public Result sendLoginSmsCode(String mobile) throws ClientException, SMSException {
+        //
+        int count = this.count(new LambdaQueryWrapper<SmsLogEntity>().eq(SmsLogEntity::getMobile,mobile).eq(SmsLogEntity::getType,Integer.valueOf(10)).apply(" TO_DAYS(send_time) = TO_DAYS(NOW()) "));
+        if (count >= SmsTemplateConstants.SEND_MAXIMIZE) {
+            return Result.error(ErrorMsgCode.D_400001);
+        }
+        Object var1 = redisService.getCacheObject(RedisKeySaltConstant.REDIS_LOGIN_VALID_CODE_KEY+mobile);
+        if (Objects.nonNull(var1)) {
+            SmsLogEntity smsLog = (SmsLogEntity) var1;
+            Long currentTime = System.currentTimeMillis();
+            Long sendTime = smsLog.getSendTime().getTime();
+            if ((currentTime - sendTime) / 1000 < smsLog.getValidTime()) {
+                return Result.error(ErrorMsgCode.D_400002);
+            }
+        }
+        int checkCode = RandomCodeUtil.RandomCheckCode();
+
+        try {
+            boolean res = sendMobileVerifyCode(mobile, checkCode);
+            if (!res) {
+                return Result.error(ErrorMsgCode.D_400003);
+            }
+            log.error("SmsLog ---- = "+checkCode);
+            SmsLogEntity smsLog = new SmsLogEntity();
+            smsLog.setVerifyCode(String.valueOf(checkCode));
+            smsLog.setMobile(mobile);
+            smsLog.setType(Integer.valueOf(10));
+            //无需关注id  验证的是手机号码
+            smsLog.setUserId(null);
+            smsLog.setValidTime(60);
+            smsLog.setSendTime(new Date());
+            smsLog.setStatus(1);
+            this.baseMapper.insert(smsLog);
+            redisService.setCacheObject(RedisKeySaltConstant.REDIS_LOGIN_VALID_CODE_KEY+mobile,smsLog,120L, TimeUnit.MINUTES);
+        } catch (ClientException e) {
+            return Result.error(e.getMessage());
+        }
+        return Result.ok();
+    }
+
+
+    /**
+     * 发送手机验证码短信
+     *
+     * @param mobile    手机
+     * @param checkCode 验证码
+     */
+    public boolean sendMobileVerifyCode(String mobile, Integer checkCode) throws ClientException {
+        return true;
+        // return SmsUtil.sendSms(smsProperties.getSmsCheckCodeTemplate(), JSON.toJSONString(ImmutableMap.of("number", checkCode)), mobile,smsProperties.getSmsAccessKeyId(),smsProperties.getSmsAccessKeyIdSecret());
+    }
+}

+ 160 - 0
storlead-sms/src/main/java/com/storlead/util/SmsUtil.java

@@ -0,0 +1,160 @@
+package com.storlead.util;
+
+import com.alibaba.fastjson.JSON;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import com.google.common.collect.ImmutableMap;
+import com.storlead.sms.constants.SmsTemplateConstants;
+import com.storlead.sms.exception.SMSException;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 短信工具类
+ *
+ * @author blank
+ * @since 2018/5/17 上午11:11
+ */
+@Log4j2
+public class SmsUtil {
+
+    /**
+     * 转账对象为 json 字符串
+     *
+     * @param obj 要转换的对象
+     * @return 转换后的 json 字符串
+     */
+    private static String mapToJSONString(Object obj) {
+        return JSON.toJSONString(obj);
+    }
+
+    /**
+     * 发送手机验证码短信
+     *
+     * @param mobile    手机
+     * @param checkCode 验证码
+     */
+    public static boolean sendCheckCode(String mobile, Integer checkCode) throws ClientException,SMSException {
+        return sendSms(SmsTemplateConstants.SMS_CHECK_CODE_TEMPLATE, mapToJSONString(ImmutableMap.of("number", checkCode)), mobile);
+    }
+
+    /**
+     * 通过阿里短信向指定手机发送指定模板 ID 的短信
+     *
+     * @param templateCode  短信模板 ID
+     * @param templateParam 短信模板参数
+     * @param phoneNum      短信发送手机号
+     * @return true 短信接口请求成功(!不是发送结果 是否成功 发送结果需要重新写短信发送查询接口来查询) / false 短信接口请求失败
+     * @author blank 2017/10/30 上午11:31
+     */
+    public static boolean sendSms(String templateCode, String templateParam, String phoneNum) throws ClientException,SMSException {
+
+        if (!StringUtils.isEmpty(templateParam)) {
+            Map<String, Object> strMap = JSON.parseObject(templateParam, HashMap.class);
+            strMap.forEach((k,v)->{
+                String temp = v.toString();
+                if (StringUtils.isNotBlank(temp)) {
+                    if (temp.length() > 20) {
+                        String s  = temp.substring(0, 18) + "..";
+                        strMap.put(k, s);
+                    }
+                }
+            });
+            templateParam = JSON.toJSONString(strMap);
+        }
+        //设置超时时间-可自行调整
+        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
+        //初始化ascClient需要的几个参数
+        //短信API产品名称(短信产品名固定,无需修改)
+        final String product = "Dysmsapi";
+        //短信API产品域名(接口地址固定,无需修改)
+        final String domain = "dysmsapi.aliyuncs.com";
+        //替换成你的AK
+        //        final String accessKeyId = mns_accesskeyid;//你的accessKeyId,参考本文档步骤2
+        //        final String accessKeySecret = mns_accesskeysecret;//你的accessKeySecret,参考本文档步骤2
+        //初始化ascClient,暂时不支持多region(请勿修改)
+        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", SmsTemplateConstants.SMS_ACCESS_KEY, SmsTemplateConstants.SMS_ACCESS_KEY_SECRET);
+        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+        //组装请求对象
+        SendSmsRequest request = new SendSmsRequest();
+        //使用post提交
+        request.setMethod(MethodType.POST);
+        //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
+        request.setPhoneNumbers(phoneNum);
+        //必填:短信签名-可在短信控制台中找到
+        request.setSignName("领存技术");
+        //必填:短信模板-可在短信控制台中找到
+        request.setTemplateCode(templateCode);
+        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+        //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
+//        request.setTemplateParam("{\"store\":\"Tom\", \"code\":\"123\"}");
+        request.setTemplateParam(templateParam);
+        //可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
+        //request.setSmsUpExtendCode("90997");
+        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+//        request.setOutId("callback");
+        //请求失败这里会抛ClientException异常
+        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
+        if (sendSmsResponse.getCode() != null && "OK".equals(sendSmsResponse.getCode())) {
+            //请求成功
+            log.info("短信发送成功 对应模板 ID ----> {}, 对应手机---> {}", templateCode, phoneNum);
+            return true;
+        } else {
+            throw new SMSException("短信发送失败:" + sendSmsResponse.getMessage());
+//            log.error("短信发送失败 " + sendSmsResponse.getMessage());
+//            return false;
+        }
+
+    }
+
+
+    /**
+     * @param userName    订单通知的用户
+     * @param mobile      订单通知的手机号码
+     * @param orderNumber 订单号
+     * @param duetime     尾款最后支付时间
+     * @Author: timo
+     * @Date: 2018/11/25 17:48
+     * @Description: 客户尾款支付提醒
+     * <p>
+     *
+     * 模版类型: 短信通知
+     * 模版名称: 客户尾款支付提醒
+     * 模版CODE: SMS_152513457
+     * 模版内容: 尊敬的${usename},尾号为${ordernumber}的订单已完成生产,请您在${duetime}内支付尾款。领存将在尾款到账后发货。
+     * 申请说明: 通知用户支付尾款
+     *
+     */
+    public static void leftAmtPaymentSmsNotice(String userName, String mobile, String orderNumber, String duetime) throws ClientException, SMSException {
+        Map<String, String> paramMap = new HashMap<>();
+        paramMap.put("usename", userName);
+        paramMap.put("ordernumber", orderNumber.substring(orderNumber.length() - 4));
+        paramMap.put("duetime", duetime+"天");
+        sendSms("SMS_152513457", JSON.toJSONString(paramMap), mobile);
+    }
+
+    public static void main(String[] args) {
+        try {
+            sendSms(SmsTemplateConstants.SMS_CHECK_CODE_TEMPLATE, mapToJSONString(ImmutableMap.of("number", 123456)), "18118724055");
+            String s = "11112222333344445555";
+            System.out.println(s.substring(0,18));
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+}

+ 23 - 0
storlead-sms/src/main/resources/mapper/SmsLogMapper.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.storlead.user.sms.mapper.SmsLogMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" extends="com.storlead.framework.mybatis.mapper.SysBaseFieldMapper.BaseResultMap" type="com.storlead.sms.pojo.entity.SmsLogEntity">
+        <id column="sms_log_id" property="smsLogId" />
+        <result column="user_id" property="userId" />
+        <result column="mobile" property="mobile" />
+        <result column="verify_code" property="verifyCode" />
+        <result column="message" property="message" />
+        <result column="status" property="status" />
+        <result column="type" property="type" />
+        <result column="send_time" property="sendTime" />
+        <result column="valid_time" property="validTime" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, user_id, mobile, verify_code, message, `type` ,status, send_time, valid_time, <include refid="com.storlead.framework.mybatis.mapper.SysBaseFieldMapper.Base_Column_List"></include>
+    </sql>
+
+</mapper>

+ 2 - 11
storlead-user/src/main/java/com/storlead/user/controller/UserApiController.java

@@ -1,6 +1,5 @@
 package com.storlead.user.controller;
 
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -13,13 +12,10 @@ import com.storlead.framework.web.assemble.Result;
 import com.storlead.user.pojo.dto.SetUserDetailDTO;
 import com.storlead.user.pojo.dto.UserParam;
 import com.storlead.user.pojo.entity.DeptEntity;
-import com.storlead.user.pojo.entity.RoleEntity;
 import com.storlead.user.pojo.entity.UserEntity;
-import com.storlead.user.pojo.entity.UserRoleEntity;
 import com.storlead.user.pojo.vo.SetUserDetailVo;
 import com.storlead.user.pojo.vo.UserVo;
 import com.storlead.user.service.IDepartService;
-import com.storlead.user.service.IRoleService;
 import com.storlead.user.service.IUserRoleService;
 import com.storlead.user.service.IUserService;
 import io.swagger.annotations.Api;
@@ -27,7 +23,6 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -38,7 +33,6 @@ import javax.annotation.Resource;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
-import java.util.stream.Collectors;
 
 /**
  * @program: storlead-centre-platform
@@ -57,9 +51,6 @@ public class UserApiController {
     @Resource
     private IUserRoleService userRoleService;
 
-    @Resource
-    private IRoleService roleService;
-
     @Resource
     private IDepartService departService;
 
@@ -125,7 +116,7 @@ public class UserApiController {
 
         IPage<UserEntity> page = new Page<>(param.getPageIndex(),param.getPageSize());
         LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<UserEntity>(new UserEntity());
-        queryWrapper.eq(UserEntity::getIsDelete, CommonConstant.FALSE_FLAG);
+        queryWrapper.eq(UserEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
         if (StrUtil.isNotBlank(param.getBlurry())) {
             queryWrapper.like(UserEntity::getUserName,param.getBlurry()).or().like(UserEntity::getRealName,param.getBlurry());
         }
@@ -177,7 +168,7 @@ public class UserApiController {
 
         IPage<UserEntity> page = new Page<>(param.getPageIndex(),param.getPageSize());
         LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<UserEntity>(new UserEntity());
-        queryWrapper.eq(UserEntity::getIsDelete, CommonConstant.FALSE_FLAG);
+        queryWrapper.eq(UserEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
         if (StrUtil.isNotBlank(param.getBlurry())) {
             queryWrapper.like(UserEntity::getUserName,param.getBlurry()).or().like(UserEntity::getRealName,param.getBlurry());
         }

+ 0 - 23
storlead-user/src/main/java/com/storlead/user/service/IRoleService.java

@@ -1,23 +0,0 @@
-package com.storlead.user.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.storlead.user.pojo.entity.RoleEntity;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * <p>
- * 角色表 服务类
- * </p>
- *
- * @Author chenkq
- * @since 2018-12-19
- */
-public interface IRoleService extends IService<RoleEntity> {
-    List<RoleEntity> findByUserId(Long userId);
-
-    Set<Long> getMenuIdsByRoleId(Long roleId,Integer isApp);
-
-    Set<Long> getdeptIdsByRoleId(Long roleId);
-}

+ 1 - 2
storlead-user/src/main/java/com/storlead/user/service/impl/UserRoleServiceImpl.java

@@ -36,8 +36,7 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRoleEnt
     private IDepartService departService;
     @Resource
     private ICompanyService companyService;
-    @Resource
-    private IRoleService roleService;
+
     private final String[] scopeType = {"全部", "本公司", "自定义","仅自己","本部门"};
 
     @Override

+ 5 - 5
storlead-user/src/main/java/com/storlead/user/service/impl/UserServiceImpl.java

@@ -53,15 +53,15 @@ public class UserServiceImpl extends MyBaseServiceImpl<UserMapper, UserEntity> i
 
 	@Resource
 	private UserMapper userMapper;
-	@Autowired
+	@Resource
 	private ICompanyService companyService;
-	@Autowired
+	@Resource
 	private ISubCompanyService subCompanyService;
-	@Autowired
+	@Resource
 	private IDepartService departService;
-	@Autowired
+	@Resource
 	private IJobService jobService;
-	@Autowired
+	@Resource
 	private CorpWeChatService corpWeChatService;
 	@Resource
 	private PasswordEncoder passwordEncoder;

+ 17 - 0
storlead-wx/src/main/java/com/storlead/wx/pojo/vo/SummaryInfoVO.java

@@ -0,0 +1,17 @@
+package com.storlead.wx.pojo.vo;
+
+import lombok.Data;
+
+/**
+ * @program: storlead-centre-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-12-17 17:16
+ */
+@Data
+public class SummaryInfoVO {
+    private Long earliestTime;
+    private Long lastestTime;
+    private String name;
+    private String acctid;
+}

+ 13 - 0
storlead-wx/src/main/java/com/storlead/wx/properties/CorpWeChatConstants.java

@@ -195,6 +195,19 @@ public class CorpWeChatConstants {
     public final static String GET_USER_LOGIN_URL = "https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info?access_token=ACCESS_TOKEN";
 
 
+    /**
+     * 企业可通过具有调用权限的应用,获取应用可见范围内指定员工指定日期内的打卡日报统计数据。
+     * access_token	是	string	调用接口凭证,获取方式参考:文档-获取access_token。
+     * starttime	是	uint32	获取日报的开始时间。0点Unix时间戳
+     * endtime	是	uint32	获取日报的结束时间。0点Unix时间戳
+     * useridlist	是	string[]	获取日报的userid列表。
+     * 单个userid不少于1字节,不多于64字节
+     * 可填充个数:1 ~ 100
+     * */
+    public final static String GETCHECKIN_DAYDATA_URL = "    https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckin_daydata?access_token=ACCESS_TOKEN";
+
+
+
 
 
 

+ 3 - 0
storlead-wx/src/main/java/com/storlead/wx/service/CorpWeChatService.java

@@ -3,6 +3,7 @@ package com.storlead.wx.service;
 
 import cn.hutool.json.JSONObject;
 import com.storlead.framework.common.vo.UserVo;
+import com.storlead.wx.pojo.vo.SummaryInfoVO;
 import com.storlead.wx.pojo.vo.WechatAppBO;
 import com.storlead.wx.pojo.vo.WechatToken;
 
@@ -117,4 +118,6 @@ public interface CorpWeChatService {
 
     boolean sendTextCardMsgByUserIdByAppCode(@NotNull String title, @NotNull String description, @NotNull String redirectionUrl, Set<String> users, Set<Long> deptSet,String appCode);
 
+
+    List<SummaryInfoVO> getCheckinDayData(List<String> userIdList);
 }

+ 12 - 8
storlead-wx/src/main/java/com/storlead/wx/service/impl/CorpWeChatServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.google.common.collect.ImmutableMap;
 import com.storlead.framework.common.vo.UserVo;
 import com.storlead.wx.pojo.vo.CorpWeChatUserVO;
+import com.storlead.wx.pojo.vo.SummaryInfoVO;
 import com.storlead.wx.pojo.vo.WechatAppBO;
 import com.storlead.wx.pojo.vo.WechatToken;
 import com.storlead.wx.properties.CorpWeChatConstants;
@@ -26,10 +27,7 @@ import javax.validation.constraints.NotNull;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.time.LocalDateTime;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 
 /**
  * 企业微信实现类
@@ -45,10 +43,7 @@ public class CorpWeChatServiceImpl implements CorpWeChatService {
     @Resource
     private WechatTokenService wechatTokenService;
 
-    @Value("${environment}")
-    private  String environment;
-
-    @Autowired
+    @Resource
     private RedissonClient redisson;
 
 
@@ -320,6 +315,15 @@ public class CorpWeChatServiceImpl implements CorpWeChatService {
         }
     }
 
+    @Override
+    public List<SummaryInfoVO> getCheckinDayData(List<String> userIdList) {
+
+        String token = this.getAccessToken().getToken();
+        List<SummaryInfoVO> checkinData = CorpWechatUtil.getUserCheckinDayData(CorpWeChatConstants.GETCHECKIN_DAYDATA_URL,token,userIdList);
+        return checkinData;
+    }
+
+
     private String getDevUrl(String dev){
         switch (dev){
             case "dev":

+ 33 - 3
storlead-wx/src/main/java/com/storlead/wx/util/CorpWechatUtil.java

@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.extension.exceptions.ApiException;
 import com.storlead.wx.pojo.vo.CorpWeChatDeptVO;
 import com.storlead.wx.pojo.vo.CorpWeChatUserVO;
+import com.storlead.wx.pojo.vo.SummaryInfoVO;
 import com.storlead.wx.pojo.vo.WechatToken;
 import com.storlead.wx.properties.CorpWeChatConstants;
 import lombok.SneakyThrows;
@@ -14,9 +15,7 @@ import org.apache.commons.lang3.StringUtils;
 
 import javax.validation.constraints.NotNull;
 import java.net.URLEncoder;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -147,6 +146,37 @@ public class CorpWechatUtil {
         return null;
     }
 
+    /**
+     * 获取员工打卡数据
+     * @param url
+     * @param accessToken
+     * @param useridlist
+     * @return
+     */
+    public static List<SummaryInfoVO> getUserCheckinDayData(@NotNull String url, @NotNull String accessToken, List<String> useridlist) {
+
+        Map<String,Object> paramMap = new HashMap<>();
+        paramMap.put("starttime","1599062400");
+        paramMap.put("endtime","1599062400");
+        paramMap.put("useridlist",useridlist);
+
+        String resultStr = HttpUtil.post(url.replace("ACCESS_TOKEN", accessToken),paramMap);
+        if (StringUtils.isNotEmpty(resultStr)) {
+            log.debug("查询所有用户---> {}", resultStr);
+            JSONObject jsonResult = new JSONObject(resultStr);
+            int errCode = jsonResult.getInt("errcode");
+            String errMsg = jsonResult.getStr("errmsg");
+            if (CorpWeChatConstants.RETURN_SUCCESS_CODE == errCode) {
+                log.info("获取打开信息: {} ", jsonResult.getJSONArray("userlist").toString());
+                String json = jsonResult.getJSONArray("userlist").toString();
+                List<SummaryInfoVO> infos = JSON.parseArray(json,SummaryInfoVO.class);
+                // com.alibaba.fastjson.JSONObject.(json,List<CorpWeChatUserVO>)
+                return infos;
+            }
+        }
+        return null;
+    }
+
     /**
      * 获取访问用户身份
      *