README.md
@@ -1,131 +0,0 @@ <p align="center"> <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png"> </p> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.2</h1> <h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4> <p align="center"> <a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.2-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> </p> ## 平台简介 若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 * 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。 * 后端采用Spring Boot、Spring Cloud & Alibaba。 * 注册中心、配置中心选型Nacos,权限认证使用Redis。 * 流量控制框架选型Sentinel,分布式事务选型Seata。 * 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Cloud-Vue3](https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3),保持同步更新。 * 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) * 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip) * 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console) #### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。 ## 系统模块 ~~~ com.ruoyi ├── ruoyi-ui // 前端框架 [80] ├── ruoyi-gateway // 网关模块 [8080] ├── ruoyi-auth // 认证中心 [9200] ├── ruoyi-api // 接口模块 │ └── ruoyi-api-system // 系统接口 ├── ruoyi-common // 通用模块 │ └── ruoyi-common-core // 核心模块 │ └── ruoyi-common-datascope // 权限范围 │ └── ruoyi-common-datasource // 多数据源 │ └── ruoyi-common-log // 日志记录 │ └── ruoyi-common-redis // 缓存服务 │ └── ruoyi-common-seata // 分布式事务 │ └── ruoyi-common-security // 安全模块 │ └── ruoyi-common-swagger // 系统接口 ├── ruoyi-modules // 业务模块 │ └── ruoyi-system // 系统模块 [9201] │ └── ruoyi-gen // 代码生成 [9202] │ └── ruoyi-job // 定时任务 [9203] │ └── ruoyi-file // 文件服务 [9300] ├── ruoyi-visual // 图形化管理模块 │ └── ruoyi-visual-monitor // 监控中心 [9100] ├──pom.xml // 公共依赖 ~~~ ## 架构图 <img src="https://oscimg.oschina.net/oscnet/up-82e9722ecb846786405a904bafcf19f73f3.png"/> ## 内置功能 1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 3. 岗位管理:配置系统用户所属担任职务。 4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 7. 参数管理:对系统动态配置常用参数。 8. 通知公告:系统通知公告信息发布维护。 9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 10. 登录日志:系统登录日志记录查询包含登录异常。 11. 在线用户:当前系统中活跃用户状态监控。 12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 14. 系统接口:根据业务代码自动生成相关的api接口文档。 15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 16. 在线构建器:拖动表单元素生成相应的HTML代码。 17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 ## 在线体验 - admin/admin123 - 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。 演示地址:http://ruoyi.vip 文档地址:http://doc.ruoyi.vip ## 演示图 <table> <tr> <td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-4148b24f58660a9dc347761e4cf6162f28f.png"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-ece3fd37a3d4bb75a3926e905a3c5629055.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td> </tr> <tr> <td><img src="https://oscimg.oschina.net/oscnet/up-ff9e3066561574aca73005c5730c6a41f15.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td> </tr> </table> ## 若依微服务交流群 QQ群: [](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [](https://jq.qq.com/?_wv=1027&k=FqImHgH2) 点击按钮入群。 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/dto/AppMiniRegisterDto.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.system.api.domain.dto; import com.ruoyi.system.api.domain.dto.AppBaseDto; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author jqs34 * @ClassName AppMiniRegisterDto * @description: TODO * @date 2023年02月13日 * @version: 1.0 */ @Data public class AppMiniRegisterDto extends AppBaseDto { @ApiModelProperty(value = "openid") private String miniOpenid; @ApiModelProperty(value = "wxUnionid") private String wxUnionid; @ApiModelProperty(value = "手机code") private String mobileCode; } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/sys/SysLogininfor.java
@@ -40,6 +40,9 @@ @Excel(name = "访问时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date accessTime; @Excel(name = "登陆端0系统1商户端2员工端3用户端") private Integer loginFrom; public Long getInfoId() { return infoId; @@ -99,4 +102,12 @@ { this.accessTime = accessTime; } public Integer getLoginFrom() { return loginFrom; } public void setLoginFrom(Integer loginFrom) { this.loginFrom = loginFrom; } } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/AppMiniRegisterVo.java
File was renamed from ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/domain/vo/AppUserAuthorizeVo.java @@ -1,17 +1,18 @@ package com.ruoyi.member.domain.vo; package com.ruoyi.system.api.domain.vo; import com.ruoyi.system.api.domain.poji.sys.SysUser; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author jqs34 * @ClassName AppUserAuthorizeDto * @ClassName AppMiniRegisterDto * @description: TODO * @date 2023年02月13日 * @version: 1.0 */ @Data public class AppUserAuthorizeVo { public class AppMiniRegisterVo { @ApiModelProperty(value = "微信openid") private String openid; @@ -24,4 +25,7 @@ @ApiModelProperty(value = "用户手机") private String mobile; @ApiModelProperty(value = "用户信息") private SysUser sysUser; } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteMemberFallbackFactory.java
@@ -1,6 +1,8 @@ package com.ruoyi.system.api.factory; import com.ruoyi.common.core.domain.R; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.domain.vo.AppMiniRegisterVo; import com.ruoyi.system.api.service.RemoteMemberService; import com.ruoyi.system.api.domain.dto.AppMemberBindingDto; import com.ruoyi.system.api.domain.dto.AppMemberGoodsTypeDto; @@ -44,6 +46,11 @@ } @Override public R<AppMiniRegisterVo> miniRegister(AppMiniRegisterDto appUserRegisterDto) { return R.fail("注册用户失败:" + throwable.getMessage()); } @Override public R<List<AppUserCouponVo>> listVoUserCouponByUserId(Long userId) { return R.fail("获取用户优惠券失败:" + throwable.getMessage()); } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/AppMiniLoginVo.java
@@ -23,6 +23,9 @@ @ApiModelProperty(value = "微信sessionKey") private String sessionKey; @ApiModelProperty(value = "用户手机") private String mobile; @ApiModelProperty(value = "用户信息") private SysUser sysUser; } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteMemberService.java
@@ -4,7 +4,9 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.system.api.domain.dto.AppMemberBindingDto; import com.ruoyi.system.api.domain.dto.AppMemberGoodsTypeDto; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.domain.vo.AppMiniRegisterVo; import com.ruoyi.system.api.domain.vo.AppUserCouponVo; import com.ruoyi.system.api.factory.RemoteMemberFallbackFactory; import com.ruoyi.system.api.model.AppMiniLoginDto; @@ -29,7 +31,19 @@ @PostMapping("/member/miniLogin") public R<AppMiniLoginVo> miniLogin(@RequestBody AppMiniLoginDto appMiniLoginDto); /** * 小程序注册 * @param appUserRegisterDto * @return */ @PostMapping("/member/miniRegister") public R<AppMiniRegisterVo> miniRegister(@RequestBody AppMiniRegisterDto appUserRegisterDto); /** * 通过userid获取用户优惠 * @param userId * @return */ @PostMapping("/member/listVoUserCouponByUserId") public R<List<AppUserCouponVo>> listVoUserCouponByUserId(@RequestBody Long userId); ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java
@@ -2,6 +2,7 @@ import javax.servlet.http.HttpServletRequest; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.model.AppMiniLoginDto; import com.ruoyi.system.api.model.AppMiniLoginVo; import io.swagger.annotations.Api; @@ -58,7 +59,15 @@ return R.ok(tokenService.createMiniToken(appMiniLoginVo)); } @ApiOperation("小程序注册") @PostMapping("miniRegister") public R<?> miniRegister(@RequestBody AppMiniRegisterDto appUserRegisterDto) { // 小程序用户登录 AppMiniLoginVo appMiniLoginVo = sysLoginService.miniRegister(appUserRegisterDto); // 获取登录token return R.ok(tokenService.createMiniToken(appMiniLoginVo)); } @DeleteMapping("logout") public R<?> logout(HttpServletRequest request) ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
@@ -1,9 +1,12 @@ package com.ruoyi.auth.service; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.domain.vo.AppMiniRegisterVo; import com.ruoyi.system.api.service.RemoteMemberService; import com.ruoyi.system.api.service.RemoteShopService; import com.ruoyi.system.api.domain.vo.ShopRelUserVo; import com.ruoyi.system.api.model.*; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.ruoyi.common.core.constant.CacheConstants; @@ -55,28 +58,28 @@ // 用户名或密码为空 错误 if (StringUtils.isAnyBlank(username, password)) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写",Constants.FROM_SYSTEM); throw new ServiceException("用户/密码必须填写"); } // 密码如果不在指定范围内 错误 if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围",Constants.FROM_SYSTEM); throw new ServiceException("用户密码不在指定范围"); } // 用户名不在指定范围内 错误 if (username.length() < UserConstants.USERNAME_MIN_LENGTH || username.length() > UserConstants.USERNAME_MAX_LENGTH) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围",Constants.FROM_SYSTEM); throw new ServiceException("用户名不在指定范围"); } // IP黑名单校验 String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST)); if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单",Constants.FROM_SYSTEM); throw new ServiceException("很遗憾,访问IP已被列入系统黑名单"); } // 查询用户信息 @@ -84,7 +87,7 @@ if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在",Constants.FROM_SYSTEM); throw new ServiceException("登录用户:" + username + " 不存在"); } @@ -97,16 +100,16 @@ SysUser user = userResult.getData().getSysUser(); if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除",Constants.FROM_SYSTEM); throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); } if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员",Constants.FROM_SYSTEM); throw new ServiceException("对不起,您的账号:" + username + " 已停用"); } passwordService.validate(user, password); recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功",Constants.FROM_SYSTEM); return userInfo; } @@ -122,29 +125,69 @@ throw new ServiceException(userResult.getMsg()); } AppMiniLoginVo userInfo = userResult.getData(); SysUser user = userResult.getData().getSysUser(); SysUser user = userInfo.getSysUser(); if(user!=null){ String username = user.getUserName(); // IP黑名单校验 String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST)); if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单",Constants.FROM_MINI_APP); throw new ServiceException("很遗憾,访问IP已被列入系统黑名单"); } if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除",Constants.FROM_MINI_APP); throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); } if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员",Constants.FROM_MINI_APP); throw new ServiceException("对不起,您的账号:" + username + " 已停用"); } recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功",Constants.FROM_MINI_APP); } return userInfo; } public AppMiniLoginVo miniRegister(AppMiniRegisterDto appUserRegisterDto) { // 查询用户信息 R<AppMiniRegisterVo> userResult = remoteMemberService.miniRegister(appUserRegisterDto); if (R.FAIL == userResult.getCode()) { throw new ServiceException(userResult.getMsg()); } AppMiniRegisterVo appMiniRegisterVo = userResult.getData(); AppMiniLoginVo userInfo = new AppMiniLoginVo(); userInfo.setMiniOpenid(appMiniRegisterVo.getOpenid()); userInfo.setWxUnionid(appMiniRegisterVo.getUnionid()); userInfo.setMobile(appMiniRegisterVo.getMobile()); SysUser user = appMiniRegisterVo.getSysUser(); userInfo.setSysUser(user); if(user!=null){ String username = user.getUserName(); // IP黑名单校验 String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST)); if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单",Constants.FROM_MINI_APP); throw new ServiceException("很遗憾,访问IP已被列入系统黑名单"); } if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除",Constants.FROM_MINI_APP); throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); } if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员",Constants.FROM_MINI_APP); throw new ServiceException("对不起,您的账号:" + username + " 已停用"); } recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功",Constants.FROM_MINI_APP); } return userInfo; } /** * 企业微信H5登录 @@ -164,17 +207,17 @@ String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST)); if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单",Constants.FROM_SHOP); throw new ServiceException("很遗憾,访问IP已被列入系统黑名单"); } if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除",Constants.FROM_SHOP); throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); } if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员",Constants.FROM_SHOP); throw new ServiceException("对不起,您的账号:" + username + " 已停用"); } // 查询用户商户 @@ -188,14 +231,14 @@ } userInfo.setShopId(shopInfo.getShopId()); recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功",Constants.FROM_SHOP); return userInfo; } public void logout(String loginName) { recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功",Constants.FROM_SYSTEM); } /** @@ -231,6 +274,6 @@ { throw new ServiceException(registerResult.getMsg()); } recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功"); recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功",Constants.FROM_SYSTEM); } } ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysRecordLogService.java
@@ -28,12 +28,13 @@ * @param message 消息内容 * @return */ public void recordLogininfor(String username, String status, String message) public void recordLogininfor(String username, String status, String message,Integer loginFrom) { SysLogininfor logininfor = new SysLogininfor(); logininfor.setUserName(username); logininfor.setIpaddr(IpUtils.getIpAddr()); logininfor.setMsg(message); logininfor.setLoginFrom(loginFrom); // 日志状态 if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) { ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
@@ -172,4 +172,15 @@ */ public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", "org.springframework", "org.apache", "com.ruoyi.common.core.utils.file" }; /** 登录端 */ public static final Integer FROM_SYSTEM = 0; public static final Integer FROM_SHOP = 1; public static final Integer FROM_STAFF = 2; public static final Integer FROM_MINI_APP = 3; } ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java
@@ -28,6 +28,11 @@ public static final String AUTHORIZATION_HEADER = "authorization"; /** * 登录端 */ public static final String LOGIN_FROM = "login_from"; /** * 请求来源 */ public static final String FROM_SOURCE = "from-source"; ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
@@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.system.api.model.AppMiniLoginVo; import com.ruoyi.system.api.model.OauthUserVo; import com.ruoyi.system.api.model.QwH5LoginVo; @@ -61,7 +62,7 @@ claimsMap.put(SecurityConstants.USER_KEY, token); claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); claimsMap.put(SecurityConstants.LOGIN_FROM, Constants.FROM_STAFF); // 接口返回信息 Map<String, Object> rspMap = new HashMap<String, Object>(); rspMap.put("access_token", JwtUtils.createToken(claimsMap)); @@ -75,6 +76,12 @@ public Map<String, Object> createMiniToken(AppMiniLoginVo appMiniLoginVo) { LoginUser loginUser = new LoginUser(); // Jwt存储信息 Map<String, Object> claimsMap = new HashMap<String, Object>(); // 接口返回信息 Map<String, Object> rspMap = new HashMap<String, Object>(); //用户为空只返回openid if(appMiniLoginVo.getSysUser()!=null){ loginUser.setSysUser(appMiniLoginVo.getSysUser()); String token = IdUtils.fastUUID(); Long userId = loginUser.getSysUser().getUserId(); @@ -84,17 +91,17 @@ loginUser.setUsername(userName); loginUser.setIpaddr(IpUtils.getIpAddr()); refreshToken(loginUser); // Jwt存储信息 Map<String, Object> claimsMap = new HashMap<String, Object>(); claimsMap.put(SecurityConstants.USER_KEY, token); claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); // 接口返回信息 Map<String, Object> rspMap = new HashMap<String, Object>(); claimsMap.put(SecurityConstants.LOGIN_FROM, Constants.FROM_MINI_APP); rspMap.put("access_token", JwtUtils.createToken(claimsMap)); rspMap.put("expires_in", expireTime); } if(StringUtils.isNotBlank(appMiniLoginVo.getMobile())){ rspMap.put("mobile",appMiniLoginVo.getMobile() ); } rspMap.put("wx_unionid", appMiniLoginVo.getWxUnionid()); rspMap.put("mini_openid", appMiniLoginVo.getMiniOpenid()); return rspMap; } @@ -120,7 +127,7 @@ claimsMap.put(SecurityConstants.USER_KEY, token); claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); claimsMap.put(SecurityConstants.LOGIN_FROM, Constants.FROM_SHOP); // 接口返回信息 OauthUserVo oauthUserVo = new OauthUserVo(); oauthUserVo.setShopId(qwH5LoginVo.getShopId()); ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/console/MemberController.java
@@ -2,14 +2,15 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.security.annotation.InnerAuth; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.domain.vo.AppMiniRegisterVo; import com.ruoyi.member.service.member.MemberService; import com.ruoyi.member.service.member.UserCouponService; import com.ruoyi.system.api.domain.dto.AppMemberBindingDto; import com.ruoyi.system.api.domain.dto.AppMemberGoodsTypeDto; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.domain.vo.AppUserCouponVo; import com.ruoyi.system.api.domain.vo.MerHomeShopTotalVo; import com.ruoyi.system.api.model.AppMiniLoginDto; import com.ruoyi.system.api.model.AppMiniLoginVo; import io.swagger.annotations.ApiOperation; @@ -60,6 +61,16 @@ return R.ok(appMiniLoginVo); } @PostMapping(value = "/miniRegister") @ApiOperation(value = "小程序注册") public R<AppMiniRegisterVo> miniRegister(@RequestBody AppMiniRegisterDto appUserRegisterDto) { AppMiniRegisterVo appUserRegisterVo = memberService.miniRegister(appUserRegisterDto); if(appUserRegisterVo ==null){ return R.fail("注册失败!"); } return R.ok(appUserRegisterVo); } /** * @description: 获取用户优惠券 * @author jqs34 ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/miniapp/AppMemberController.java
@@ -3,19 +3,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.member.domain.dto.AppUserAuthorizeDto; import com.ruoyi.member.domain.dto.MerCashMemberPageDto; import com.ruoyi.member.domain.vo.AppSuggestPageVo; import com.ruoyi.member.domain.vo.AppUserAuthorizeVo; import com.ruoyi.member.domain.vo.AppUserInfoVo; import com.ruoyi.member.domain.vo.MerCashMemberPageVo; import com.ruoyi.member.service.member.MemberService; import com.ruoyi.member.service.member.MemberSuggestService; import com.ruoyi.system.api.domain.dto.AppEditUserDto; import com.ruoyi.system.api.domain.dto.AppSuggestPageDto; import com.ruoyi.system.api.domain.dto.AppUserSuggestDto; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.domain.poji.sys.SysUser; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; @@ -45,14 +39,7 @@ private MemberSuggestService memberSuggestService; @RequestMapping(value = "/getAppUserAuthorize", method = RequestMethod.POST) @ApiOperation(value = "获取用户授权信息") public R<AppUserAuthorizeVo> getAppUserAuthorize(@RequestBody AppUserAuthorizeDto appUserAuthorizeDto) { Long userId = SecurityUtils.getUserId(); appUserAuthorizeDto.setUserId(userId); AppUserAuthorizeVo appUserAuthorizeVo = memberService.getAppUserAuthorize(appUserAuthorizeDto); return R.ok(appUserAuthorizeVo); } @RequestMapping(value = "/getAppUserInfo", method = RequestMethod.POST) @ApiOperation(value = "获取用户信息") ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/domain/dto/AppUserAuthorizeDto.java
File was deleted ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/mapper/member/MemberMapper.java
@@ -28,6 +28,15 @@ * @version 1.0 */ Member selectMemberByUserId(Long userId); /** * @description: TODO * @author jqs34 * @date 2023/4/30 12:41 * @version 1.0 */ Member selectMemberByMobile(String mobile); /** * 通过openid获取会员 * @param miniOpenid ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/impl/member/MemberServiceImpl.java
@@ -7,10 +7,10 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.bean.BeanUtils; import com.ruoyi.common.core.utils.uuid.IdUtils; import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.member.domain.dto.*; import com.ruoyi.member.domain.pojo.member.MemberNurse; @@ -19,6 +19,8 @@ import com.ruoyi.member.service.member.MemberNurseService; import com.ruoyi.member.service.member.MemberService; import com.ruoyi.member.util.HttpUtils; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.domain.vo.AppMiniRegisterVo; import com.ruoyi.system.api.service.RemoteConfigService; import com.ruoyi.system.api.service.RemoteOrderService; import com.ruoyi.system.api.service.RemoteShopService; @@ -91,6 +93,9 @@ @Resource private RemoteConfigService remoteConfigService; @Resource private RedisService redisService; /** * @description: TODO * @author jqs34 @@ -129,48 +134,15 @@ sessionKey = session.getSessionKey(); //获取用户 Member member = memberMapper.getOneByMiniOpenid(openid); SysUser sysUser; if(member==null){ //创建新用户 String memberId = IdUtils.simpleUUID(); sysUser = new SysUser(); sysUser.setUserName(memberId); sysUser.setUserType("03"); sysUser.setNickName("鸿瑞堂用户"); sysUser.setAvatar("https://hongruitang.oss-cn-beijing.aliyuncs.com/default.png"); String password = "hongruitang"; sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser = sysUserService.registerUser(sysUser).getData(); log.info("sysUser1-----------------"+sysUser.toString()); member = new Member(); member.setUserId(sysUser.getUserId()); member.setDelFlag(0); member.setNickName("鸿瑞堂用户"); member.setAvatar("https://hongruitang.oss-cn-beijing.aliyuncs.com/default.png"); member.setMemberId(memberId); member.setRelationShopId(1L); member.setWxUnionid(unionid); member.setMiniOpenid(openid); member.setBindingFlag(0); member.setCreateTime(new Date()); log.info("member-----------------"+member.toString()); this.saveOrUpdate(member); }else{ log.info("member2"+member.toString()); R<SysUser> sysUser1 = sysUserService.getSysUser(member.getUserId()); log.info("sysUser1"+ sysUser1.getCode() + " : " + sysUser1.getMsg()); sysUser = sysUser1.getData(); log.info("sysUser"+sysUser.toString()); SysUser sysUser = null; if(member!=null){ sysUser = sysUserService.getSysUser(member.getUserId()).getData(); } appMiniLoginVo.setMiniOpenid(openid); appMiniLoginVo.setWxUnionid(unionid); appMiniLoginVo.setSysUser(sysUser); appMiniLoginVo.setSessionKey(sessionKey); stringRedisTemplate.opsForValue().set(SecurityConstant.SESSION_KEY+openid,sessionKey); }else{ log.info("null"); return null; redisService.setCacheObject(SecurityConstant.SESSION_KEY+openid,sessionKey,1L,TimeUnit.DAYS); } log.info("appMiniLoginVo"+appMiniLoginVo.toString()); return appMiniLoginVo; @@ -178,22 +150,21 @@ /** * 获取授权信息 * @param appUserAuthorizeDto * @param appUserRegisterDto * @return */ @Override public AppUserAuthorizeVo getAppUserAuthorize(AppUserAuthorizeDto appUserAuthorizeDto){ Member member = this.getById(appUserAuthorizeDto.getUserId()); AppUserAuthorizeVo appUserAuthorizeVo = new AppUserAuthorizeVo(); public AppMiniRegisterVo miniRegister(AppMiniRegisterDto appUserRegisterDto){ AppMiniRegisterVo appUserRegisterVo = new AppMiniRegisterVo(); String mobile = null; if(StringUtils.isBlank(member.getMobile())){ //获取code接口在redis里存放的sessionkey用于解密 String sessionkey = stringRedisTemplate.opsForValue().get(SecurityConstant.SESSION_KEY+ member.getMiniOpenid()); String sessionkey = redisService.getCacheObject(SecurityConstant.SESSION_KEY+ appUserRegisterDto.getMiniOpenid()); if(StringUtils.isBlank(sessionkey)){ throw new ServiceException(AppErrorConstant.USER_NOT_LOGIN); } try { String accessToken = stringRedisTemplate.opsForValue().get("wx_access_token"); //获取微信token用于解密手机 String accessToken = redisService.getCacheObject(SecurityConstant.WX_TOKEN); if (StringUtils.isBlank(accessToken)) { String responseAccessToken = getAccessTokenByWX(); JSONObject jsonAccessToken = JSONObject.parseObject(responseAccessToken); @@ -204,10 +175,11 @@ throw new ServiceException(errmsg); } else { expiresIn = expiresIn - 100; stringRedisTemplate.opsForValue().set("wx_access_token", accessToken, expiresIn.intValue(), TimeUnit.SECONDS); redisService.setCacheObject(SecurityConstant.WX_TOKEN, accessToken, Long.valueOf(expiresIn), TimeUnit.SECONDS); } } String responseUserPhoneNumber = getMobileByWX(accessToken, appUserAuthorizeDto.getMobileCode()); //解密手机 String responseUserPhoneNumber = getMobileByWX(accessToken, appUserRegisterDto.getMobileCode()); JSONObject jsonUserPhoneNumber = JSONObject.parseObject(responseUserPhoneNumber); String errcode = jsonUserPhoneNumber.getString("errcode"); String errmsg = jsonUserPhoneNumber.getString("errmsg"); @@ -220,35 +192,50 @@ } catch (Exception e) { e.printStackTrace(); } Member oldMember = this.getByMobile(mobile); if(oldMember!=null){ member.setNickName(oldMember.getNickName()); member.setGender(oldMember.getGender()); member.setReferrer(oldMember.getReferrer()); member.setBirthday(oldMember.getBirthday()); member.setBindingFlag(1); member.setRelationShopId(oldMember.getRelationShopId()); oldMember.setDelFlag(1); oldMember.setMiniOpenid(oldMember.getMiniOpenid()+"已删除"); this.saveOrUpdate(oldMember); }else{ //更新用户手机信息 SysUser sysUser = new SysUser(); sysUser.setUserId(appUserAuthorizeDto.getUserId()); sysUser.setPhonenumber(mobile); sysUserService.updateUserMobile(sysUser); member.setNickName(sysUser.getNickName()); if(StringUtils.isBlank(mobile)){ return null; } member.setMobile(mobile); //判断openid是否被其他手机号占用 Member checkMember = memberMapper.getOneByMiniOpenid(appUserRegisterDto.getMiniOpenid()); if(checkMember!=null&&!checkMember.getMobile().equals(mobile)){ throw new ServiceException("微信号换绑手机需联系客服"); } Member member = memberMapper.selectMemberByMobile(mobile); SysUser sysUser; //获取用户为空则新建 if(member == null){ //创建新用户 sysUser = new SysUser(); sysUser.setUserName(mobile+"-3"); sysUser.setUserType("03"); sysUser.setNickName("鸿瑞堂用户"); sysUser.setAvatar("https://hongruitang.oss-cn-beijing.aliyuncs.com/default.png"); String password = "hongruitang"; sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser = sysUserService.registerUser(sysUser).getData(); member = new Member(); String memberId = IdUtils.simpleUUID(); member.setUserId(sysUser.getUserId()); member.setDelFlag(0); member.setNickName("鸿瑞堂用户"); member.setAvatar("https://hongruitang.oss-cn-beijing.aliyuncs.com/default.png"); member.setMemberId(memberId); member.setRelationShopId(1L); member.setBindingFlag(0); member.setCreateTime(new Date()); }else{ sysUser = sysUserService.getSysUser(member.getUserId()).getData(); } member.setWxUnionid(appUserRegisterDto.getWxUnionid()); member.setMiniOpenid(appUserRegisterDto.getMiniOpenid()); log.info("member-----------------"+member.toString()); this.saveOrUpdate(member); }else{ mobile = member.getMobile(); } appUserAuthorizeVo.setMobile(mobile); appUserAuthorizeVo.setNickName(member.getNickName()); appUserAuthorizeVo.setOpenid(member.getMiniOpenid()); appUserAuthorizeVo.setUnionid(member.getWxUnionid()); return appUserAuthorizeVo; appUserRegisterVo.setMobile(mobile); appUserRegisterVo.setNickName(member.getNickName()); appUserRegisterVo.setOpenid(member.getMiniOpenid()); appUserRegisterVo.setUnionid(member.getWxUnionid()); appUserRegisterVo.setSysUser(sysUser); return appUserRegisterVo; } public static String getAccessTokenByWX() throws Exception { ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/member/MemberService.java
@@ -6,8 +6,9 @@ import com.ruoyi.system.api.domain.dto.AppEditUserDto; import com.ruoyi.system.api.domain.dto.AppMemberBindingDto; import com.ruoyi.system.api.domain.dto.AppMemberGoodsTypeDto; import com.ruoyi.system.api.domain.dto.AppMiniRegisterDto; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.domain.vo.MerHomeShopTotalVo; import com.ruoyi.system.api.domain.vo.AppMiniRegisterVo; import com.ruoyi.system.api.model.AppMiniLoginDto; import com.ruoyi.system.api.model.AppMiniLoginVo; import com.baomidou.mybatisplus.extension.service.IService; @@ -41,10 +42,10 @@ /** * 获取授权信息 * @param appUserAuthorizeDto * @param appUserRegisterDto * @return */ AppUserAuthorizeVo getAppUserAuthorize(AppUserAuthorizeDto appUserAuthorizeDto); AppMiniRegisterVo miniRegister(AppMiniRegisterDto appUserRegisterDto); /** * 获取用户信息 ruoyi-modules/ruoyi-member/src/main/resources/mapper/member/MemberMapper.xml
@@ -57,6 +57,11 @@ where user_id = #{userId} </select> <select id="selectMemberByUserId" parameterType="Long" resultMap="MemberResult"> <include refid="selectMemberVo"/> where mobile = #{mobile} </select> <insert id="insertMember" parameterType="com.ruoyi.system.api.domain.poji.member.Member"> insert into t_member <trim prefix="(" suffix=")" suffixOverrides=","> ruoyi-modules/ruoyi-system/src/main/resources/mapper/sys/SysLogininforMapper.xml
@@ -11,15 +11,16 @@ <result property="ipaddr" column="ipaddr" /> <result property="msg" column="msg" /> <result property="accessTime" column="access_time" /> <result property="loginFrom" column="login_from" /> </resultMap> <insert id="insertLogininfor" parameterType="SysLogininfor"> insert into sys_logininfor (user_name, status, ipaddr, msg, access_time) values (#{userName}, #{status}, #{ipaddr}, #{msg}, sysdate()) insert into sys_logininfor (user_name, status, ipaddr, msg, access_time,login_from) values (#{userName}, #{status}, #{ipaddr}, #{msg}, sysdate(),loginFrom) </insert> <select id="selectLogininforList" parameterType="SysLogininfor" resultMap="SysLogininforResult"> select info_id, user_name, ipaddr, status, msg, access_time from sys_logininfor select info_id, user_name, ipaddr, status, msg, access_time, login_from from sys_logininfor <where> <if test="ipaddr != null and ipaddr != ''"> AND ipaddr like concat('%', #{ipaddr}, '%') @@ -30,12 +31,18 @@ <if test="userName != null and userName != ''"> AND user_name like concat('%', #{userName}, '%') </if> <if test="loginFrom != null and loginFrom != ''"> AND login_from = #{loginFrom} </if> <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 --> AND access_time >= #{params.beginTime} </if> <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> AND access_time <= #{params.endTime} </if> <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> AND access_time <= #{params.endTime} </if> </where> order by info_id desc </select>