From c43915105c8da8aa63f0644d1c50934fa3b3b38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=95=AC=E7=A7=91?= <1810539219@qq.com> Date: Mon, 6 Jul 2026 09:28:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=8F=8A=E5=B8=A6=E7=A7=9F=E6=88=BF=E7=9A=84=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/school/MorningCheckInController.java | 1 - .../common/WxAppUserLoginController.java | 170 ------ .../controller/system/SysLoginController.java | 7 +- .../src/main/resources/application-druid.yml | 12 +- .../common/constant/TenantConstants.java | 35 ++ .../common/core/domain/entity/SysDept.java | 22 + .../common/core/domain/entity/SysRole.java | 11 + .../core/domain/entity/SysTenantBo.java | 112 ++++ .../domain/entity/SysTenantPackageBo.java | 49 ++ .../core/domain/entity/SysTenantVo.java | 93 ++++ .../common/core/domain/entity/SysUser.java | 28 + .../common/core/domain/model/LoginBody.java | 11 + .../foodpurchase/common/utils/PageResult.java | 44 ++ .../common/utils/StringUtils.java | 25 +- .../config/ClientLoginAuthProvider.java | 131 +++++ ...omUsernamePasswordAuthenticationToken.java | 17 + .../framework/config/SecurityConfig.java | 150 +++--- .../service/ClientUserDetailsService.java | 9 + .../impl/ClientUserDetailsServiceImpl.java | 73 +++ .../web/service/SysLoginService.java | 41 +- .../web/service/WxAppLoginService.java | 185 ------- .../vo/SupplierDeliveryItemUpdateVO.java | 1 - .../foodpurchase/system/domain/SysTenant.java | 103 ++++ .../system/domain/SysTenantPackage.java | 71 +++ .../system/domain/vo/SysTenantPackageVo.java | 50 ++ .../system/mapper/SysDeptMapper.java | 8 + .../system/mapper/SysRoleMapper.java | 2 + .../system/mapper/SysRoleMenuMapper.java | 3 + .../system/mapper/SysTenantMapper.java | 35 ++ .../system/mapper/SysTenantPackageMapper.java | 24 + .../system/mapper/SysUserMapper.java | 10 + .../system/service/ISysTenantService.java | 86 +++ .../service/impl/SysTenantServiceImpl.java | 492 ++++++++++++++++++ .../main/resources/mapper/SysTenantMapper.xml | 149 ++++++ .../mapper/SysTenantPackageMapper.xml | 79 +++ .../resources/mapper/system/SysRoleMapper.xml | 6 + .../mapper/system/SysRoleMenuMapper.xml | 13 +- .../resources/mapper/system/SysUserMapper.xml | 32 +- .../mapper/system/WxSysDeptMapper.xml | 43 ++ pom.xml | 10 +- 40 files changed, 1975 insertions(+), 468 deletions(-) delete mode 100644 fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/wxapp/common/WxAppUserLoginController.java create mode 100644 fp-common/src/main/java/com/zf/foodpurchase/common/constant/TenantConstants.java create mode 100644 fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantBo.java create mode 100644 fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantPackageBo.java create mode 100644 fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantVo.java create mode 100644 fp-common/src/main/java/com/zf/foodpurchase/common/utils/PageResult.java create mode 100644 fp-framework/src/main/java/com/zf/foodpurchase/framework/config/ClientLoginAuthProvider.java create mode 100644 fp-framework/src/main/java/com/zf/foodpurchase/framework/config/CustomUsernamePasswordAuthenticationToken.java create mode 100644 fp-framework/src/main/java/com/zf/foodpurchase/framework/service/ClientUserDetailsService.java create mode 100644 fp-framework/src/main/java/com/zf/foodpurchase/framework/service/impl/ClientUserDetailsServiceImpl.java delete mode 100644 fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/WxAppLoginService.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenant.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenantPackage.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/domain/vo/SysTenantPackageVo.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantMapper.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantPackageMapper.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/service/ISysTenantService.java create mode 100644 fp-system/src/main/java/com/zf/foodpurchase/system/service/impl/SysTenantServiceImpl.java create mode 100644 fp-system/src/main/resources/mapper/SysTenantMapper.xml create mode 100644 fp-system/src/main/resources/mapper/SysTenantPackageMapper.xml diff --git a/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/web/school/MorningCheckInController.java b/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/web/school/MorningCheckInController.java index f6298b1..d1e0e72 100644 --- a/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/web/school/MorningCheckInController.java +++ b/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/web/school/MorningCheckInController.java @@ -14,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.xml.ws.soap.Addressing; import java.util.List; /** diff --git a/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/wxapp/common/WxAppUserLoginController.java b/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/wxapp/common/WxAppUserLoginController.java deleted file mode 100644 index dc225ef..0000000 --- a/fp-admin/src/main/java/com/zf/foodpurchase/fdsafe/wxapp/common/WxAppUserLoginController.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.zf.foodpurchase.fdsafe.wxapp.common; - -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.zf.foodpurchase.common.config.RuoYiConfig; -import com.zf.foodpurchase.common.constant.Constants; -import com.zf.foodpurchase.common.constant.UserConstants; -import com.zf.foodpurchase.common.core.controller.BaseController; -import com.zf.foodpurchase.common.core.domain.AjaxResult; -import com.zf.foodpurchase.common.core.domain.entity.LoginWxUser; -import com.zf.foodpurchase.common.core.domain.entity.User; -import com.zf.foodpurchase.common.core.domain.entity.WxAppUserVO; -import com.zf.foodpurchase.common.core.domain.model.WxAppLoginBody; -import com.zf.foodpurchase.common.core.domain.model.WxAppLoginUser; -import com.zf.foodpurchase.common.exception.ServiceException; -import com.zf.foodpurchase.common.exception.user.UserPasswordNotMatchException; -import com.zf.foodpurchase.common.utils.MessageUtils; -import com.zf.foodpurchase.common.utils.SecurityUtils; -import com.zf.foodpurchase.common.utils.StringUtils; -import com.zf.foodpurchase.common.utils.file.FileUploadUtils; -import com.zf.foodpurchase.common.utils.file.MimeTypeUtils; -import com.zf.foodpurchase.fdsafe.entity.WxAppUser; -import com.zf.foodpurchase.fdsafe.service.IWxAppUserService; -import com.zf.foodpurchase.fdsafe.vo.WxAppUserViewVO; -import com.zf.foodpurchase.framework.manager.AsyncManager; -import com.zf.foodpurchase.framework.manager.factory.AsyncFactory; -import com.zf.foodpurchase.framework.web.service.WxAppLoginService; -import com.zf.foodpurchase.framework.web.service.WxAppTokenService; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.validation.Valid; -import java.util.Date; - -/** - * @author:lilj - * @date:2025/5/12 - */ -@RestController -@RequestMapping("/wxapp/userLogin") -public class WxAppUserLoginController extends BaseController { - @Autowired - private IWxAppUserService wxAppUserService; - - @Autowired - private WxAppTokenService wxAppTokenService; - - @Autowired - private WxAppLoginService wxAppLoginService; - private WxAppUserVO loginWxUser; - - @PostMapping("/login") - public AjaxResult login(@RequestBody @Valid WxAppLoginBody wxAppLoginBody) { - String token = wxAppLoginService.login(wxAppLoginBody); - AjaxResult ajax = AjaxResult.success(); - ajax.put(Constants.TOKEN, token); - return ajax; - } - - @GetMapping("/getCurrentUser") - public AjaxResult getCurrentUser() { - WxAppLoginUser loginWxUser = getWxAppLoginUser(); - WxAppUserVO user = loginWxUser.getUser(); - AjaxResult response = success("查询成功"); - response.put("user", user); - return response; - } - - /** - * 可修改项:用户密码,昵称,头像,性别 - * - * @param user - * @return - */ - @PostMapping("/updateUser") - public AjaxResult updateUser(@RequestBody WxAppUserViewVO user) { - if (user == null || user.getId() == null) { - return error("用户id不能为空"); - } - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper(); - updateWrapper.eq(WxAppUser::getId, user.getId()); - updateWrapper.set(WxAppUser::getNickname, user.getNickname()); - updateWrapper.set(WxAppUser::getRealName, user.getRealName()); - updateWrapper.set(WxAppUser::getAvatarUrl, user.getAvatarUrl()); - updateWrapper.set(WxAppUser::getGender, user.getGender()); - updateWrapper.set(WxAppUser::getUpdateTime, new Date()); - boolean isUpdate = wxAppUserService.update(updateWrapper); - if (!isUpdate) { - return error("修改失败"); - } - WxAppUserVO newUser = wxAppUserService.getUserVOById(user.getId()); - WxAppLoginUser loginUser = getWxAppLoginUser(); - // 设置部门名称 - WxAppUserVO oldUser = loginUser.getUser(); - newUser.setDeptName(oldUser.getDeptName()); - loginUser.setUser(newUser); - - wxAppTokenService.setLoginWxAppUser(loginUser); - return isUpdate ? success("修改成功") : error("修改失败"); - } - - /** - * 修改用户密码 - */ - @PostMapping("/updateUserPassword") - public AjaxResult updateUserPassword(@RequestBody WxAppUserViewVO user) { - if (user == null || user.getId() == null) { - return error("用户id不能为空"); - } - pwdCheck(user.getNewPassword()); - WxAppUser old = wxAppUserService.getById(user.getId()); - if (old == null) { - return error("用户不存在"); - } - // 校验密码是否正确 - boolean isMatch = SecurityUtils.matchesPassword(user.getPassword(), old.getPassword()); - if (!isMatch) { - throw new ServiceException("原密码有误"); - } - - WxAppUser updateUser = new WxAppUser(); - updateUser.setId(user.getId()); - updateUser.setPassword(SecurityUtils.encryptPassword(user.getNewPassword())); - boolean isUpdate = wxAppUserService.updateById(updateUser); - return isUpdate ? success("密码修改成功") : error("密码修改失败"); - } - - - @GetMapping("/logout") - public AjaxResult logout() { - WxAppLoginUser wxAppLoginUser = getWxAppLoginUser(); - if (wxAppLoginUser != null) { - String token = wxAppLoginUser.getToken(); - wxAppTokenService.delLoginWxAppUser(token); - } - return AjaxResult.success("退出登录成功"); - } - - public void pwdCheck(String userPwd) { - if (StringUtils.isBlank(userPwd)) { - throw new ServiceException("新密码不能为空"); - } - // 密码如果不在指定范围内 错误 - if (userPwd.length() < UserConstants.PASSWORD_MIN_LENGTH - || userPwd.length() > UserConstants.PASSWORD_MAX_LENGTH) { - throw new ServiceException("新密码位数应大于" + UserConstants.PASSWORD_MIN_LENGTH + ",小于" + UserConstants.PASSWORD_MAX_LENGTH + "位"); - } - } - - /** - * 微信头像上传 - */ - @PostMapping(value = "/avatar", produces = "application/json;charset=UTF-8") - public AjaxResult avatar(MultipartFile file) throws Exception { - if (!file.isEmpty()) { - WxAppLoginUser loginWxUser = getWxAppLoginUser(); - // 上传文件路径 - String filePath = RuoYiConfig.getUploadPath(); - // D:/ruoyi/wxprofile/avatar - String avatar = FileUploadUtils.upload(filePath, file, MimeTypeUtils.IMAGE_EXTENSION); - - avatar = RuoYiConfig.getImagePrefix() + avatar; - return AjaxResult.success().put("avatarUrl", avatar); - } - return error("上传图片异常"); - } - - -} diff --git a/fp-admin/src/main/java/com/zf/foodpurchase/web/controller/system/SysLoginController.java b/fp-admin/src/main/java/com/zf/foodpurchase/web/controller/system/SysLoginController.java index 0e4bf3e..7836aa6 100644 --- a/fp-admin/src/main/java/com/zf/foodpurchase/web/controller/system/SysLoginController.java +++ b/fp-admin/src/main/java/com/zf/foodpurchase/web/controller/system/SysLoginController.java @@ -63,12 +63,7 @@ public class SysLoginController { */ @PostMapping("/login") public AjaxResult login(@RequestBody LoginBody loginBody) { - AjaxResult ajax = AjaxResult.success(); - // 生成令牌 - String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), - loginBody.getUuid()); - ajax.put(Constants.TOKEN, token); - return ajax; + return loginService.login(loginBody.getTenantId(), loginBody.getUsername(), loginBody.getPassword()); } /** diff --git a/fp-admin/src/main/resources/application-druid.yml b/fp-admin/src/main/resources/application-druid.yml index 1185cfa..0c88866 100644 --- a/fp-admin/src/main/resources/application-druid.yml +++ b/fp-admin/src/main/resources/application-druid.yml @@ -9,16 +9,16 @@ spring: # url: jdbc:mysql://localhost:3306/zf_shopping_mall?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # username: root # password: root123456 - url: jdbc:mysql://125.46.39.9:3306/zf_school_food?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + url: jdbc:mysql://39.165.209.170:3307/zf_school_food?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root - password: wXn*QFs_6aNvFq@qDr.gPYsfBL-XN_o2 + password: zheng_wXn_fan*QFs_6aNvFq@keji_qDr.gPYsfBL # 从库数据源 slave: # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: + #enabled: false + url: jdbc:mysql://39.165.209.170:3307/zf_shopping_mall?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: root + password: zheng_wXn_fan*QFs_6aNvFq@keji_qDr.gPYsfBL # 初始连接数 initialSize: 5 # 最小连接池数量 diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/constant/TenantConstants.java b/fp-common/src/main/java/com/zf/foodpurchase/common/constant/TenantConstants.java new file mode 100644 index 0000000..4bd668e --- /dev/null +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/constant/TenantConstants.java @@ -0,0 +1,35 @@ +package com.zf.foodpurchase.common.constant; + +/** + * 租户常量信息 + * + * @author Lion Li + */ +public interface TenantConstants { + + /** + * 超级管理员ID + */ + Long SUPER_ADMIN_ID = 1L; + + /** + * 超级管理员角色 roleKey + */ + String SUPER_ADMIN_ROLE_KEY = "super_admin"; + + /** + * 租户管理员角色 roleKey + */ + String TENANT_ADMIN_ROLE_KEY = "tenant_admin"; + + /** + * 租户管理员角色名称 + */ + String TENANT_ADMIN_ROLE_NAME = "租户管理员"; + + /** + * 默认租户ID + */ + String DEFAULT_TENANT_ID = "000000"; + +} diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysDept.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysDept.java index 60bf45d..c167837 100644 --- a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysDept.java +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysDept.java @@ -25,6 +25,10 @@ public class SysDept extends BaseEntity /** 父商户ID */ private Long parentId; + private String tenantId; + + private String isTenant; + /** 祖级列表 */ private String ancestors; @@ -235,11 +239,29 @@ public class SysDept extends BaseEntity this.children = children; } + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getIsTenant() { + return isTenant; + } + + public void setIsTenant(String isTenant) { + this.isTenant = isTenant; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("deptId", getDeptId()) .append("parentId", getParentId()) + .append("tenantId", getTenantId()) + .append("isTenant", getIsTenant()) .append("ancestors", getAncestors()) .append("deptName", getDeptName()) .append("orderNum", getOrderNum()) diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysRole.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysRole.java index c1aa5af..b4770b7 100644 --- a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysRole.java +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysRole.java @@ -35,6 +35,8 @@ public class SysRole extends BaseEntity @Excel(name = "角色排序") private Integer roleSort; + private String tenantId; + /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */ @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") private String dataScope; @@ -219,6 +221,14 @@ public class SysRole extends BaseEntity this.permissions = permissions; } + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) @@ -226,6 +236,7 @@ public class SysRole extends BaseEntity .append("roleName", getRoleName()) .append("roleKey", getRoleKey()) .append("roleSort", getRoleSort()) + .append("tenantId", getTenantId()) .append("dataScope", getDataScope()) .append("menuCheckStrictly", isMenuCheckStrictly()) .append("deptCheckStrictly", isDeptCheckStrictly()) diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantBo.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantBo.java new file mode 100644 index 0000000..d5d7801 --- /dev/null +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantBo.java @@ -0,0 +1,112 @@ +package com.zf.foodpurchase.common.core.domain.entity; + + +import com.zf.foodpurchase.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * 租户业务对象 sys_tenant + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysTenantBo extends BaseEntity { + + /** + * id + */ + @NotNull(message = "id不能为空") + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 联系人 + */ + @NotBlank(message = "联系人不能为空") + private String contactUserName; + + /** + * 联系电话 + */ + @NotBlank(message = "联系电话不能为空") + private String contactPhone; + + /** + * 企业名称 + */ + @NotBlank(message = "企业名称不能为空") + private String companyName; + + /** + * 用户名(创建系统用户) + */ + @NotBlank(message = "用户名不能为空") + private String username; + + /** + * 密码(创建系统用户) + */ + @NotBlank(message = "密码不能为空") +// @Pattern(regexp = RegexConstants.PASSWORD, message = "{user.password.format.valid}", groups = { AddGroup.class }) + private String password; + + /** + * 统一社会信用代码 + */ + private String licenseNumber; + + /** + * 地址 + */ + private String address; + + /** + * 域名 + */ + private String domain; + + /** + * 企业简介 + */ + private String intro; + + /** + * 备注 + */ + private String remark; + + /** + * 租户套餐编号 + */ + @NotNull(message = "租户套餐不能为空") + private Long packageId; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + private String status; + + private Long deptId; + +} diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantPackageBo.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantPackageBo.java new file mode 100644 index 0000000..cf56d91 --- /dev/null +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantPackageBo.java @@ -0,0 +1,49 @@ +package com.zf.foodpurchase.common.core.domain.entity; + + +import com.zf.foodpurchase.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户套餐业务对象 sys_tenant_package + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysTenantPackageBo extends BaseEntity { + + /** + * 租户套餐id + */ + private Long packageId; + + /** + * 套餐名称 + */ + private String packageName; + + /** + * 关联菜单id + */ + private Long[] menuIds; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + private String status; + + +} diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantVo.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantVo.java new file mode 100644 index 0000000..90b602a --- /dev/null +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysTenantVo.java @@ -0,0 +1,93 @@ +package com.zf.foodpurchase.common.core.domain.entity; + + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 租户视图对象 sys_tenant + * + * @author Michelle.Chung + */ +@Data +public class SysTenantVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 联系人 + */ + private String contactUserName; + + /** + * 联系电话 + */ + private String contactPhone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 统一社会信用代码 + */ + private String licenseNumber; + + /** + * 地址 + */ + private String address; + + /** + * 域名 + */ + private String domain; + + /** + * 企业简介 + */ + private String intro; + + /** + * 备注 + */ + private String remark; + + /** + * 租户套餐编号 + */ + private Long packageId; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + private String status; + + private Long deptId; + + private Long createDept; +} diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysUser.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysUser.java index cdeaff6..701c703 100644 --- a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysUser.java +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/entity/SysUser.java @@ -29,6 +29,16 @@ public class SysUser extends BaseEntity { @Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号") private Long userId; + /** + * 学校id + */ + private Integer organiId; + + /** + * 租户id + */ + private String tenantId; + /** * 部门ID */ @@ -369,10 +379,28 @@ public class SysUser extends BaseEntity { this.roleId = roleId; } + public Integer getOrganiId() { + return organiId; + } + + public void setOrganiId(Integer organiId) { + this.organiId = organiId; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("userId", getUserId()) + .append("organiId", getOrganiId()) + .append("tenantId", getTenantId()) .append("deptId", getDeptId()) .append("userName", getUserName()) .append("nickName", getNickName()) diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/model/LoginBody.java b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/model/LoginBody.java index e672869..b566586 100644 --- a/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/model/LoginBody.java +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/core/domain/model/LoginBody.java @@ -7,6 +7,9 @@ package com.zf.foodpurchase.common.core.domain.model; */ public class LoginBody { + + private String tenantId; + /** /** * 用户名 */ @@ -66,4 +69,12 @@ public class LoginBody { this.uuid = uuid; } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } } diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/utils/PageResult.java b/fp-common/src/main/java/com/zf/foodpurchase/common/utils/PageResult.java new file mode 100644 index 0000000..49143bc --- /dev/null +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/utils/PageResult.java @@ -0,0 +1,44 @@ +package com.zf.foodpurchase.common.utils; + +import java.io.Serializable; +import java.util.List; + +public class PageResult implements Serializable { + + private Integer pageIndex;//当前页 + private Integer pages;//总页数 + private Long totles;//总条数 + private List result; //结果集 + + public Integer getPageIndex() { + return pageIndex; + } + + public void setPageIndex(Integer pageIndex) { + this.pageIndex = pageIndex; + } + + public Integer getPages() { + return pages; + } + + public void setPages(Integer pages) { + this.pages = pages; + } + + public Long getTotles() { + return totles; + } + + public void setTotles(Long totles) { + this.totles = totles; + } + + public List getResult() { + return result; + } + + public void setResult(List result) { + this.result = result; + } +} diff --git a/fp-common/src/main/java/com/zf/foodpurchase/common/utils/StringUtils.java b/fp-common/src/main/java/com/zf/foodpurchase/common/utils/StringUtils.java index 65f2be5..a382539 100644 --- a/fp-common/src/main/java/com/zf/foodpurchase/common/utils/StringUtils.java +++ b/fp-common/src/main/java/com/zf/foodpurchase/common/utils/StringUtils.java @@ -1,11 +1,8 @@ package com.zf.foodpurchase.common.utils; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; + import org.springframework.util.AntPathMatcher; import com.zf.foodpurchase.common.constant.Constants; import com.zf.foodpurchase.common.core.text.StrFormatter; @@ -681,4 +678,20 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils } return sb.toString(); } + + public static List commaStrToLongList(String str) { + // 1. 处理空值/空字符串:直接返回空集合,避免NPE + if (str == null || str.trim().isEmpty()) { + return new ArrayList<>(); + } + + // 2. 拆分+清理空格+转换为Long+收集为List + return Arrays.asList(str.split(",")) // 按逗号拆分字符串为数组 + .stream() // 转为流处理 + .map(String::trim) // 去除每个元素的前后空格(处理" 4 , 5 "的情况) + .filter(s -> !s.isEmpty()) // 过滤拆分后空字符串(比如",,6"拆分出的空元素) + .map(Long::valueOf) // 字符串转Long(非数字会抛NumberFormatException) + .collect(Collectors.toList()); // 收集为List + } + } \ No newline at end of file diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/ClientLoginAuthProvider.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/ClientLoginAuthProvider.java new file mode 100644 index 0000000..ec20c0a --- /dev/null +++ b/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/ClientLoginAuthProvider.java @@ -0,0 +1,131 @@ +package com.zf.foodpurchase.framework.config; + +import cn.hutool.core.lang.Assert; +import com.zf.foodpurchase.framework.service.ClientUserDetailsService; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsPasswordService; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; + +public class ClientLoginAuthProvider extends AbstractUserDetailsAuthenticationProvider { + + + private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword"; + + private PasswordEncoder passwordEncoder; + + /** + * The password used to perform {@link PasswordEncoder#matches(CharSequence, String)} + * on when the user is not found to avoid SEC-2056. This is necessary, because some + * {@link PasswordEncoder} implementations will short circuit if the password is not + * in a valid format. + */ + private volatile String userNotFoundEncodedPassword; + + private ClientUserDetailsService userDetailsService; + + private UserDetailsPasswordService userDetailsPasswordService; + + public ClientLoginAuthProvider(ClientUserDetailsService clientUserDetailsService) { + this.userDetailsService = clientUserDetailsService; + setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder()); + } + + @Override + @SuppressWarnings("deprecation") + protected void additionalAuthenticationChecks(UserDetails userDetails, + UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + if (authentication.getCredentials() == null) { + this.logger.debug("Failed to authenticate since no credentials provided"); + throw new BadCredentialsException(this.messages + .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); + } + String presentedPassword = authentication.getCredentials().toString(); + if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { + this.logger.debug("Failed to authenticate since password does not match stored value"); + throw new BadCredentialsException(this.messages + .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); + } + } + + @Override + protected void doAfterPropertiesSet() { + Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); + } + + @Override + protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + CustomUsernamePasswordAuthenticationToken auth = (CustomUsernamePasswordAuthenticationToken) authentication; + + //多个参数 + UserDetails loadedUser = userDetailsService.loadUserByUsername(username,auth.getTenantId()); + + if (loadedUser == null) { + throw new InternalAuthenticationServiceException( + "UserDetailsService returned null, which is an interface contract violation"); + } + return loadedUser; + } + + @Override + protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, + UserDetails user) { + boolean upgradeEncoding = this.userDetailsPasswordService != null + && this.passwordEncoder.upgradeEncoding(user.getPassword()); + if (upgradeEncoding) { + String presentedPassword = authentication.getCredentials().toString(); + String newPassword = this.passwordEncoder.encode(presentedPassword); + user = this.userDetailsPasswordService.updatePassword(user, newPassword); + } + return super.createSuccessAuthentication(principal, authentication, user); + } + + private void prepareTimingAttackProtection() { + if (this.userNotFoundEncodedPassword == null) { + this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD); + } + } + + private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) { + if (authentication.getCredentials() != null) { + String presentedPassword = authentication.getCredentials().toString(); + this.passwordEncoder.matches(presentedPassword, this.userNotFoundEncodedPassword); + } + } + + /** + * Sets the PasswordEncoder instance to be used to encode and validate passwords. If + * not set, the password will be compared using + * {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()} + * @param passwordEncoder must be an instance of one of the {@code PasswordEncoder} + * types. + */ + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); + this.passwordEncoder = passwordEncoder; + this.userNotFoundEncodedPassword = null; + } + + protected PasswordEncoder getPasswordEncoder() { + return this.passwordEncoder; + } + + public void setUserDetailsService(ClientUserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + + protected ClientUserDetailsService getUserDetailsService() { + return this.userDetailsService; + } + + public void setUserDetailsPasswordService(UserDetailsPasswordService userDetailsPasswordService) { + this.userDetailsPasswordService = userDetailsPasswordService; + } + +} diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/CustomUsernamePasswordAuthenticationToken.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/CustomUsernamePasswordAuthenticationToken.java new file mode 100644 index 0000000..7c05ba4 --- /dev/null +++ b/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/CustomUsernamePasswordAuthenticationToken.java @@ -0,0 +1,17 @@ +package com.zf.foodpurchase.framework.config; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; + +public class CustomUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { + private final String tenantId; + + public CustomUsernamePasswordAuthenticationToken(Object principal, Object credentials, String tenantId) { + super(principal, credentials); + this.tenantId = tenantId; + } + + public String getTenantId() { + return tenantId; + } +} + diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/SecurityConfig.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/SecurityConfig.java index 7bfc379..eb90ee1 100644 --- a/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/SecurityConfig.java +++ b/fp-framework/src/main/java/com/zf/foodpurchase/framework/config/SecurityConfig.java @@ -1,5 +1,6 @@ package com.zf.foodpurchase.framework.config; +import com.zf.foodpurchase.framework.service.ClientUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; @@ -9,8 +10,12 @@ import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -23,28 +28,15 @@ import com.zf.foodpurchase.framework.security.filter.JwtAuthenticationTokenFilte import com.zf.foodpurchase.framework.security.handle.AuthenticationEntryPointImpl; import com.zf.foodpurchase.framework.security.handle.LogoutSuccessHandlerImpl; +import javax.annotation.Resource; + /** * spring security配置 * * @author ruoyi */ -@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true) -@Configuration -public class SecurityConfig -{ - /** - * 自定义用户认证逻辑 - */ - @Autowired - @Qualifier("userDetailsServiceImpl") - private UserDetailsService userDetailsService; - - /** - * 自定义微信小程序/APP认证逻辑类 - */ - @Autowired - @Qualifier("wxAppUserDetailsService") - private UserDetailsService wxAppUserDetailsService; +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 认证失败处理类 @@ -75,31 +67,22 @@ public class SecurityConfig */ @Autowired private PermitAllUrlProperties permitAllUrl; - /** - * 身份验证实现 - */ - @Bean("authenticationManager") - @Primary - public AuthenticationManager authenticationManager() - { - DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); - daoAuthenticationProvider.setUserDetailsService(userDetailsService); - daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); - AuthenticationManager manager=new ProviderManager(daoAuthenticationProvider); - return manager; + + + @Resource + private ClientUserDetailsService clientUserDetailsService; + + @Bean + public ClientLoginAuthProvider clientLoginAuthProvider(){ + ClientLoginAuthProvider provider = new ClientLoginAuthProvider(clientUserDetailsService); + provider.setPasswordEncoder(bCryptPasswordEncoder()); + return provider; } - /** - * wxApp登录身份验证实现 - */ - @Bean("wxAppAuthenticationManager") - public AuthenticationManager wxAppAuthenticationManager() - { - DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); - daoAuthenticationProvider.setUserDetailsService(wxAppUserDetailsService); - daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); - AuthenticationManager manager=new ProviderManager(daoAuthenticationProvider); - return manager; + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); } /** @@ -117,49 +100,45 @@ public class SecurityConfig * rememberMe | 允许通过remember-me登录的用户访问 * authenticated | 用户登录后可访问 */ - @Bean - protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception - { - return httpSecurity - // CSRF禁用,因为不使用session - .csrf(csrf -> csrf.disable()) - // 禁用HTTP响应标头 - .headers((headersCustomizer) -> { - headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin()); - }) - // 认证失败处理类 - .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler)) - // 基于token,所以不需要session - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - // 注解标记允许匿名访问的url - .authorizeHttpRequests((requests) -> { - permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll()); + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + + // 注解标记允许匿名访问的url + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests(); + permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll()); + + httpSecurity + // CSRF禁用,因为不使用session + .csrf().disable() + // 认证失败处理类 + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + // 基于token,所以不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 过滤请求 + .authorizeRequests() // 对于登录login 注册register 验证码captchaImage 允许匿名访问 - requests.antMatchers("/login", "/register", "/captchaImage","/wx/user/mockLogin","/wx/user/login","/wxapp/userLogin/login").permitAll() - // 静态资源,可匿名访问 - .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() - .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() - // 微信静态资源访问不被拦截 - .antMatchers("/wx/static/**","/wx/payApi/").permitAll() - // 部分接口开放,不受权限访问限制 - .antMatchers("/wx/area/**").permitAll() - // 微信体验功能,部分接口权限放开 - // 首页查询商品查询,轮播图查询,类别查询,按类别查询商品接口 - .antMatchers("/wx/products/indexProducts","/wx/dict/type/product_category","/wx/products/category","/wx/carousel/list").permitAll() - // 临时放开权限校验,共开发测试使用 - // .antMatchers("/wx/**").permitAll() - .antMatchers("/wx/payApi/**").permitAll() - // 除上面外的所有请求全部需要鉴权认证 - .anyRequest().authenticated(); - }) - // 添加Logout filter - .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler)) - // 添加JWT filter - .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) - // 添加CORS filter - .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class) - .addFilterBefore(corsFilter, LogoutFilter.class) - .build(); + .antMatchers("/login", "/register", "/captchaImage","/wx/user/mockLogin","/wx/user/login","/wxapp/userLogin/login").permitAll() + // 静态资源,可匿名访问 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() + .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() + // 微信静态资源访问不被拦截 + .antMatchers("/wx/static/**","/wx/payApi/").permitAll() + // 部分接口开放,不受权限访问限制 + .antMatchers("/wx/area/**").permitAll() + // 微信体验功能,部分接口权限放开 + // 首页查询商品查询,轮播图查询,类别查询,按类别查询商品接口 + .antMatchers("/wx/products/indexProducts","/wx/dict/type/product_category","/wx/products/category","/wx/carousel/list").permitAll() + // 临时放开权限校验,共开发测试使用 + // .antMatchers("/wx/**").permitAll() + .antMatchers("/wx/payApi/**").permitAll() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated(); + // 添加Logout filter + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + + httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); } /** @@ -170,4 +149,11 @@ public class SecurityConfig { return new BCryptPasswordEncoder(); } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // auth.inMemoryAuthentication().passwordEncoder(bCryptPasswordEncoder()); + //auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); + auth.authenticationProvider(clientLoginAuthProvider()); + } } diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/service/ClientUserDetailsService.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/service/ClientUserDetailsService.java new file mode 100644 index 0000000..5964656 --- /dev/null +++ b/fp-framework/src/main/java/com/zf/foodpurchase/framework/service/ClientUserDetailsService.java @@ -0,0 +1,9 @@ +package com.zf.foodpurchase.framework.service; + +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public interface ClientUserDetailsService { + UserDetails loadUserByUsername(String username, String tenantId) throws UsernameNotFoundException; +} + diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/service/impl/ClientUserDetailsServiceImpl.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/service/impl/ClientUserDetailsServiceImpl.java new file mode 100644 index 0000000..f5d3a24 --- /dev/null +++ b/fp-framework/src/main/java/com/zf/foodpurchase/framework/service/impl/ClientUserDetailsServiceImpl.java @@ -0,0 +1,73 @@ +package com.zf.foodpurchase.framework.service.impl; + + +import com.zf.foodpurchase.common.core.domain.entity.SysUser; +import com.zf.foodpurchase.common.core.domain.model.LoginUser; +import com.zf.foodpurchase.common.enums.UserStatus; +import com.zf.foodpurchase.common.exception.ServiceException; +import com.zf.foodpurchase.common.utils.StringUtils; +import com.zf.foodpurchase.framework.web.service.SysPasswordService; +import com.zf.foodpurchase.framework.web.service.SysPermissionService; +import com.zf.foodpurchase.system.mapper.SysDeptMapper; +import com.zf.foodpurchase.system.mapper.SysRoleDeptMapper; +import com.zf.foodpurchase.system.mapper.SysUserMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import com.zf.foodpurchase.framework.service.ClientUserDetailsService; + +import javax.annotation.Resource; + +@Service("clientUserDetailsService") +public class ClientUserDetailsServiceImpl implements ClientUserDetailsService { + + private static final Logger log = LoggerFactory.getLogger(ClientUserDetailsServiceImpl.class); + + @Resource + private SysUserMapper sysUserMapper; + + @Autowired + private SysPasswordService passwordService; + + @Autowired + private SysPermissionService permissionService; + + @Autowired + private SysRoleDeptMapper roleDeptMapper; + + @Autowired + private SysDeptMapper deptMapper; + + @Override + public UserDetails loadUserByUsername(String username, String tenantId) throws UsernameNotFoundException { + // 此处即可自定义查询用户 + SysUser user = sysUserMapper.selectUserByUserNameAndTenantId(username,tenantId); + if (StringUtils.isNull(user)) + { + log.info("登录用户:{} 不存在.", username); + throw new ServiceException("登录用户:" + username + " 不存在"); + } + else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } + else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + log.info("登录用户:{} 已被停用.", username); + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } + + passwordService.validate(user); + + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) + { + return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); + } +} diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/SysLoginService.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/SysLoginService.java index da8513d..3322ac3 100644 --- a/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/SysLoginService.java +++ b/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/SysLoginService.java @@ -1,8 +1,11 @@ package com.zf.foodpurchase.framework.web.service; +import cn.hutool.core.util.ObjectUtil; import com.zf.foodpurchase.common.constant.CacheConstants; import com.zf.foodpurchase.common.constant.Constants; import com.zf.foodpurchase.common.constant.UserConstants; +import com.zf.foodpurchase.common.core.domain.AjaxResult; +import com.zf.foodpurchase.common.core.domain.entity.SysTenantVo; import com.zf.foodpurchase.common.core.domain.entity.SysUser; import com.zf.foodpurchase.common.core.domain.model.LoginUser; import com.zf.foodpurchase.common.core.redis.RedisCache; @@ -12,10 +15,12 @@ import com.zf.foodpurchase.common.utils.DateUtils; import com.zf.foodpurchase.common.utils.MessageUtils; import com.zf.foodpurchase.common.utils.StringUtils; import com.zf.foodpurchase.common.utils.ip.IpUtils; +import com.zf.foodpurchase.framework.config.CustomUsernamePasswordAuthenticationToken; import com.zf.foodpurchase.framework.manager.AsyncManager; import com.zf.foodpurchase.framework.manager.factory.AsyncFactory; import com.zf.foodpurchase.framework.security.context.AuthenticationContextHolder; import com.zf.foodpurchase.system.service.ISysConfigService; +import com.zf.foodpurchase.system.service.ISysTenantService; import com.zf.foodpurchase.system.service.ISysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -26,6 +31,9 @@ import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; /** * 登录校验方法 @@ -39,7 +47,6 @@ public class SysLoginService private TokenService tokenService; @Resource - @Qualifier("authenticationManager") private AuthenticationManager authenticationManager; @Autowired @@ -51,26 +58,39 @@ public class SysLoginService @Autowired private ISysConfigService configService; + @Autowired + private ISysTenantService tenantService; + /** * 登录验证 * * @param username 用户名 * @param password 密码 - * @param code 验证码 - * @param uuid 唯一标识 * @return 结果 */ - public String login(String username, String password, String code, String uuid) + public AjaxResult login(String tenantId, String username, String password) { // 验证码校验 - validateCaptcha(username, code, uuid); + //validateCaptcha(username, code, uuid); // 登录前置校验 - loginPreCheck(username, password); + //loginPreCheck(username, password); + if (StringUtils.isBlank(tenantId)) { + return AjaxResult.error("请选择租户"); + } + SysTenantVo tenant = tenantService.queryByTenantId(tenantId); + if (ObjectUtil.isNull(tenant)) { + return AjaxResult.error("租户不存在"); + } else if ("1".equals(tenant.getStatus())) { + return AjaxResult.error("租户已停用"); + } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) + && new Date().after(tenant.getExpireTime())) { + return AjaxResult.error("租户已过期"); + } // 用户验证 Authentication authentication = null; try { - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + CustomUsernamePasswordAuthenticationToken authenticationToken = new CustomUsernamePasswordAuthenticationToken(username, password,tenantId); AuthenticationContextHolder.setContext(authenticationToken); // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername authentication = authenticationManager.authenticate(authenticationToken); @@ -96,7 +116,12 @@ public class SysLoginService LoginUser loginUser = (LoginUser) authentication.getPrincipal(); recordLoginInfo(loginUser.getUserId()); // 生成token - return tokenService.createToken(loginUser); + String token = tokenService.createToken(loginUser); + Map map = new HashMap(); + map.put(Constants.TOKEN, token); + map.put("userId",loginUser.getUserId()); + return AjaxResult.success(map); + } /** diff --git a/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/WxAppLoginService.java b/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/WxAppLoginService.java deleted file mode 100644 index ca9722c..0000000 --- a/fp-framework/src/main/java/com/zf/foodpurchase/framework/web/service/WxAppLoginService.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.zf.foodpurchase.framework.web.service; - -import com.zf.foodpurchase.common.constant.CacheConstants; -import com.zf.foodpurchase.common.constant.Constants; -import com.zf.foodpurchase.common.constant.UserConstants; -import com.zf.foodpurchase.common.core.domain.entity.SysUser; -import com.zf.foodpurchase.common.core.domain.entity.WxAppUserVO; -import com.zf.foodpurchase.common.core.domain.model.LoginUser; -import com.zf.foodpurchase.common.core.domain.model.WxAppLoginBody; -import com.zf.foodpurchase.common.core.domain.model.WxAppLoginUser; -import com.zf.foodpurchase.common.core.redis.RedisCache; -import com.zf.foodpurchase.common.exception.ServiceException; -import com.zf.foodpurchase.common.exception.user.*; -import com.zf.foodpurchase.common.utils.DateUtils; -import com.zf.foodpurchase.common.utils.MessageUtils; -import com.zf.foodpurchase.common.utils.StringUtils; -import com.zf.foodpurchase.common.utils.ip.IpUtils; -import com.zf.foodpurchase.fdsafe.entity.WxAppUser; -import com.zf.foodpurchase.fdsafe.service.IWxAppUserService; -import com.zf.foodpurchase.framework.manager.AsyncManager; -import com.zf.foodpurchase.framework.manager.factory.AsyncFactory; -import com.zf.foodpurchase.framework.security.context.AuthenticationContextHolder; -import com.zf.foodpurchase.system.service.ISysConfigService; -import com.zf.foodpurchase.system.service.ISysUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 登录校验方法 - * - * @author ruoyi - */ -@Component -public class WxAppLoginService -{ - @Autowired - private WxAppTokenService tokenService; - - @Autowired - @Qualifier("wxAppAuthenticationManager") - private AuthenticationManager authenticationManager; - - @Autowired - private RedisCache redisCache; - - @Autowired - private IWxAppUserService wxAppUserService; - - @Autowired - private ISysConfigService configService; - - /** - * 登录验证 - * - * @param wxAppLoginBody 登录对象 - * @return 结果 - */ - public String login(WxAppLoginBody wxAppLoginBody) - { - String username = wxAppLoginBody.getUsername(); - String password = wxAppLoginBody.getPassword(); - // 验证码校验 - // validateCaptcha(username, code, uuid); - // 登录前置校验 - loginPreCheck(username, password); - // 用户验证 - Authentication authentication = null; - try - { - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); - AuthenticationContextHolder.setContext(authenticationToken); - // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername - authentication = authenticationManager.authenticate(authenticationToken); - } - catch (Exception e) - { - if (e instanceof BadCredentialsException) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); - throw new UserPasswordNotMatchException(); - } - else - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); - throw new ServiceException(e.getMessage()); - } - } - finally - { - AuthenticationContextHolder.clearContext(); - } - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); - WxAppLoginUser loginUser = (WxAppLoginUser) authentication.getPrincipal(); - recordLoginInfo(loginUser.getUserId()); - // 生成token - return tokenService.createWxAppToken(loginUser); - } - - /** - * 校验验证码 - * - * @param username 用户名 - * @param code 验证码 - * @param uuid 唯一标识 - * @return 结果 - */ - public void validateCaptcha(String username, String code, String uuid) - { - boolean captchaEnabled = configService.selectCaptchaEnabled(); - if (captchaEnabled) - { - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); - String captcha = redisCache.getCacheObject(verifyKey); - if (captcha == null) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); - throw new CaptchaExpireException(); - } - redisCache.deleteObject(verifyKey); - if (!code.equalsIgnoreCase(captcha)) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); - throw new CaptchaException(); - } - } - } - - /** - * 登录前置校验 - * @param username 用户名 - * @param password 用户密码 - */ - public void loginPreCheck(String username, String password) - { - // 用户名或密码为空 错误 - if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"))); - throw new UserNotExistsException(); - } - // 密码如果不在指定范围内 错误 - if (password.length() < UserConstants.PASSWORD_MIN_LENGTH - || password.length() > UserConstants.PASSWORD_MAX_LENGTH) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); - throw new UserPasswordNotMatchException(); - } - // 用户名不在指定范围内 错误 - if (username.length() < UserConstants.USERNAME_MIN_LENGTH - || username.length() > UserConstants.USERNAME_MAX_LENGTH) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); - throw new UserPasswordNotMatchException(); - } - // IP黑名单校验 - String blackStr = configService.selectConfigByKey("sys.login.blackIPList"); - if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked"))); - throw new BlackListException(); - } - } - - /** - * 记录登录信息 - * - * @param userId 用户ID - */ - public void recordLoginInfo(Long userId) - { - WxAppUser user = new WxAppUser(); - user.setId(userId); - user.setLoginTime(DateUtils.getNowDate()); - user.setLoginIp(IpUtils.getIpAddr()); - user.setUpdateTime(DateUtils.getNowDate()); - wxAppUserService.updateById(user); - } -} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/fdsafe/vo/SupplierDeliveryItemUpdateVO.java b/fp-system/src/main/java/com/zf/foodpurchase/fdsafe/vo/SupplierDeliveryItemUpdateVO.java index a882e11..8059b13 100644 --- a/fp-system/src/main/java/com/zf/foodpurchase/fdsafe/vo/SupplierDeliveryItemUpdateVO.java +++ b/fp-system/src/main/java/com/zf/foodpurchase/fdsafe/vo/SupplierDeliveryItemUpdateVO.java @@ -3,7 +3,6 @@ package com.zf.foodpurchase.fdsafe.vo; import com.zf.foodpurchase.common.valigroud.UpdateGroup; import com.zf.foodpurchase.common.vo.CommonVO; import lombok.Data; -import org.w3c.dom.stylesheets.LinkStyle; import javax.validation.constraints.NotBlank; import java.io.Serializable; diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenant.java b/fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenant.java new file mode 100644 index 0000000..46cf3c1 --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenant.java @@ -0,0 +1,103 @@ +package com.zf.foodpurchase.system.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.zf.foodpurchase.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 租户对象 sys_tenant + * + * @author Michelle.Chung + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_tenant") +public class SysTenant extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(value = "id") + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 联系人 + */ + private String contactUserName; + + /** + * 联系电话 + */ + private String contactPhone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 统一社会信用代码 + */ + private String licenseNumber; + + /** + * 地址 + */ + private String address; + + /** + * 域名 + */ + private String domain; + + /** + * 企业简介 + */ + private String intro; + + /** + * 备注 + */ + private String remark; + + /** + * 租户套餐编号 + */ + private Long packageId; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + private String status; + + /** + * 删除标志(0代表存在 1代表删除) + */ + @TableLogic + private String delFlag; + + private Long createDept; + +} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenantPackage.java b/fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenantPackage.java new file mode 100644 index 0000000..ae8683b --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/domain/SysTenantPackage.java @@ -0,0 +1,71 @@ +package com.zf.foodpurchase.system.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.zf.foodpurchase.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + + +/** + * 租户套餐对象 sys_tenant_package + * + * @author Michelle.Chung + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_tenant_package") +public class SysTenantPackage extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + @TableId(value = "package_id") + private Long packageId; + + /** + * 套餐名称 + */ + private String packageName; + + /** + * 关联菜单id + */ + private String menuIds; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) + */ + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 删除标志(0代表存在 1代表删除) + */ + @TableLogic + private String delFlag; + + private Long createDept; + + private String createBy; + + private Date createTime; + + private String updateBy; + + private Date updateTime; +} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/domain/vo/SysTenantPackageVo.java b/fp-system/src/main/java/com/zf/foodpurchase/system/domain/vo/SysTenantPackageVo.java new file mode 100644 index 0000000..99f689d --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/domain/vo/SysTenantPackageVo.java @@ -0,0 +1,50 @@ +package com.zf.foodpurchase.system.domain.vo; + + +import lombok.Data; + +import java.io.Serializable; + + +/** + * 租户套餐视图对象 sys_tenant_package + * + * @author Michelle.Chung + */ +@Data +public class SysTenantPackageVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + private Long packageId; + + /** + * 套餐名称 + */ + private String packageName; + + /** + * 关联菜单id + */ + private String menuIds; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + private String status; + + +} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysDeptMapper.java b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysDeptMapper.java index a0c9f8a..f412d2d 100644 --- a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysDeptMapper.java +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysDeptMapper.java @@ -115,4 +115,12 @@ public interface SysDeptMapper * @return 结果 */ public int deleteDeptById(Long deptId); + + public int updateDeptByTenantId(@Param("dept") SysDept dept, @Param("tenantId") String tenantId); + + public List selectByTenantId(@Param("tenantId") String tenantId); + + public void updateTenantId(@Param("deptIds") List deptIds, @Param("tenantId") String tenantId); + + public List selectAllZSByDeptId(Long deptId); } diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMapper.java b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMapper.java index 18ab28a..4619af5 100644 --- a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMapper.java +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMapper.java @@ -104,4 +104,6 @@ public interface SysRoleMapper * @return 结果 */ public int deleteRoleByIds(Long[] roleIds); + + public List selectRolesByTenantId(String tenantId); } diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMenuMapper.java b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMenuMapper.java index 1e7f11d..b2b33bd 100644 --- a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMenuMapper.java +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysRoleMenuMapper.java @@ -2,6 +2,7 @@ package com.zf.foodpurchase.system.mapper; import java.util.List; import com.zf.foodpurchase.system.domain.SysRoleMenu; +import org.apache.ibatis.annotations.Param; /** * 角色与菜单关联表 数据层 @@ -41,4 +42,6 @@ public interface SysRoleMenuMapper * @return 结果 */ public int batchRoleMenu(List roleMenuList); + + public int deleteRoleMenuForSync(@Param("roleIds") List roleIds, @Param("menuIds") List menuIds); } diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantMapper.java b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantMapper.java new file mode 100644 index 0000000..9eac4f7 --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantMapper.java @@ -0,0 +1,35 @@ +package com.zf.foodpurchase.system.mapper; + +import com.zf.foodpurchase.common.core.domain.entity.SysTenantBo; +import com.zf.foodpurchase.common.core.domain.entity.SysTenantVo; +import com.zf.foodpurchase.system.domain.SysTenant; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface SysTenantMapper { + + public SysTenantVo queryById(Long id); + + public List queryByCondition(SysTenantBo bo); + + public int deleteByIds(@Param("ids") List ids); + + public int updateById(SysTenant sysTenant); + + public int insert(SysTenant sysTenant); + + public SysTenantVo queryByTenantId(String tenantId); + + public List selectObjs(); + + public List queryByPackageIds(@Param("packageIds") List packageIds); + + public List queryByCompanyName(String companyName); + + public List queryByPhone(String phone); + + public List queryByTenantIds(@Param("tenantIds") List tenantIds); +} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantPackageMapper.java b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantPackageMapper.java new file mode 100644 index 0000000..957029d --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysTenantPackageMapper.java @@ -0,0 +1,24 @@ +package com.zf.foodpurchase.system.mapper; + + +import com.zf.foodpurchase.common.core.domain.entity.SysTenantPackageBo; +import com.zf.foodpurchase.system.domain.SysTenantPackage; +import com.zf.foodpurchase.system.domain.vo.SysTenantPackageVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface SysTenantPackageMapper { + + public SysTenantPackageVo selectById(Long packageId); + + public List selectList(SysTenantPackageBo sysTenantPackageBo); + + public int insert(SysTenantPackage sysTenantPackage); + + public int update(SysTenantPackage sysTenantPackage); + + public int deleteByIds(@Param("packageIds") List packageIds); +} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysUserMapper.java b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysUserMapper.java index 07ebb16..923bed2 100644 --- a/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysUserMapper.java +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/mapper/SysUserMapper.java @@ -124,4 +124,14 @@ public interface SysUserMapper * @return 结果 */ public SysUser checkEmailUnique(String email); + + + int unableUser(@Param("userIds") List userIds,@Param("statusChar") String statusChar); + + List selectUserIdsByTenantId(@Param("tenantId") String tenantId); + + int updateTenantIdOfUsers(@Param("deptIds") List deptIds,@Param("tenantId") String tenantId); + + SysUser selectUserByUserNameAndTenantId(@Param("userName") String userName,@Param("tenantId") String tenantId); + } diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/service/ISysTenantService.java b/fp-system/src/main/java/com/zf/foodpurchase/system/service/ISysTenantService.java new file mode 100644 index 0000000..51091b5 --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/service/ISysTenantService.java @@ -0,0 +1,86 @@ +package com.zf.foodpurchase.system.service; + + + +import com.zf.foodpurchase.common.core.domain.AjaxResult; +import com.zf.foodpurchase.common.core.domain.entity.SysTenantBo; +import com.zf.foodpurchase.common.core.domain.entity.SysTenantVo; + +import java.util.List; + +/** + * 租户Service接口 + * + * @author Michelle.Chung + */ +public interface ISysTenantService { + + /** + * 查询租户 + */ + SysTenantVo queryById(Long id); + + /** + * 基于租户ID查询租户 + */ + SysTenantVo queryByTenantId(String tenantId); + + /** + * 查询租户列表 + */ + AjaxResult queryPageList(SysTenantBo bo, Integer page, Integer pageSize); + + /** + * 查询租户列表 + */ + AjaxResult queryList(SysTenantBo bo); + + /** + * 新增租户 + */ + Boolean insertByBo(SysTenantBo bo); + + /** + * 修改租户 + */ + Boolean updateByBo(SysTenantBo bo); + + + /** + * 校验租户是否允许操作 + */ + void checkTenantAllowed(String tenantId); + + /** + * 校验并批量删除租户信息 + */ + Boolean deleteWithValidByIds(List ids, Boolean isValid); + + /** + * 校验企业名称是否唯一 + */ + boolean checkCompanyNameUnique(SysTenantBo bo); + + /** + * 校验联系方式是否唯一 + */ + boolean checkPhoneUnique(SysTenantBo bo); + + /** + * 校验用户名是否唯一 + */ + boolean checkUsername(SysTenantBo bo); + + /** + * 校验有效期 + */ + boolean checkExpireTime(String tenantId); + + /** + * 修改租户状态 + */ + int updateTenantStatus(SysTenantBo bo); + + Boolean deptToTenant(SysTenantBo bo); + +} diff --git a/fp-system/src/main/java/com/zf/foodpurchase/system/service/impl/SysTenantServiceImpl.java b/fp-system/src/main/java/com/zf/foodpurchase/system/service/impl/SysTenantServiceImpl.java new file mode 100644 index 0000000..37f7b70 --- /dev/null +++ b/fp-system/src/main/java/com/zf/foodpurchase/system/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,492 @@ +package com.zf.foodpurchase.system.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.BCrypt; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.zf.foodpurchase.common.constant.TenantConstants; +import com.zf.foodpurchase.common.core.domain.AjaxResult; +import com.zf.foodpurchase.common.core.domain.entity.*; +import com.zf.foodpurchase.common.core.domain.model.LoginUser; +import com.zf.foodpurchase.common.exception.ServiceException; +import com.zf.foodpurchase.common.utils.PageResult; +import com.zf.foodpurchase.common.utils.SecurityUtils; +import com.zf.foodpurchase.common.utils.StringUtils; +import com.zf.foodpurchase.common.utils.spring.SpringUtils; +import com.zf.foodpurchase.system.domain.SysRoleDept; +import com.zf.foodpurchase.system.domain.SysRoleMenu; +import com.zf.foodpurchase.system.domain.SysTenant; +import com.zf.foodpurchase.system.domain.SysUserRole; +import com.zf.foodpurchase.system.domain.vo.SysTenantPackageVo; +import com.zf.foodpurchase.system.mapper.*; +import com.zf.foodpurchase.system.service.ISysTenantService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 租户Service业务层处理 + * + * @author Michelle.Chung + */ +@RequiredArgsConstructor +@Service +public class SysTenantServiceImpl implements ISysTenantService { + + private final SysTenantMapper baseMapper; + private final SysTenantPackageMapper tenantPackageMapper; + private final SysUserMapper userMapper; + private final SysDeptMapper deptMapper; + private final SysRoleMapper roleMapper; + private final SysRoleMenuMapper roleMenuMapper; + private final SysRoleDeptMapper roleDeptMapper; + private final SysUserRoleMapper userRoleMapper; + private final SysTenantMapper sysTenantMapper; + private final SysUserMapper sysUserMapper; + private final SysDeptMapper sysDeptMapper; + + /** + * 查询租户 + */ + @Override + public SysTenantVo queryById(Long id) { + SysTenantVo sysTenantVo = baseMapper.queryById(id); + return sysTenantVo; + } + + /** + * 基于租户ID查询租户 + */ + @Override + public SysTenantVo queryByTenantId(String tenantId) { + return baseMapper.queryByTenantId(tenantId); + } + + /** + * 查询租户列表 + */ + @Override + public AjaxResult queryPageList(SysTenantBo bo, Integer page, Integer pageSize) { + PageHelper.startPage(page, pageSize); + List sysTenantVos = baseMapper.queryByCondition(bo); + PageInfo pageInfo = new PageInfo<>(sysTenantVos); + PageResult result = new PageResult(); + result.setPageIndex(page); + result.setPages(pageInfo.getPages()); + result.setTotles(pageInfo.getTotal()); + result.setResult(sysTenantVos); + return AjaxResult.success(result); + } + + /** + * 查询租户列表 + */ + @Override + public AjaxResult queryList(SysTenantBo bo) { + List sysTenantVos = baseMapper.queryByCondition(bo); + return AjaxResult.success(sysTenantVos); + } + /** + * 新增租户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(SysTenantBo bo) { + Date date = new Date(); + LoginUser loginUser = (LoginUser) SecurityUtils.getLoginUser(); + SysTenant add = BeanUtil.toBean(bo, SysTenant.class); + // 获取所有租户编号 + List tenantIds = baseMapper.selectObjs(); + String tenantId = generateTenantId(tenantIds); + add.setTenantId(tenantId); + add.setCreateDept(bo.getDeptId()); + add.setCreateTime(new Date()); + add.setCreateBy(loginUser.getUserId()+""); + add.setStatus("0"); + boolean flag = baseMapper.insert(add) > 0; + if (!flag) { + throw new ServiceException("创建租户失败"); + } + bo.setId(add.getId()); + + // 根据套餐创建角色 + Long roleId = createTenantRole(tenantId, bo.getPackageId(),bo.getCompanyName()); + + // 创建部门: 公司名是部门名称 + SysDept dept = new SysDept(); + dept.setTenantId(tenantId); + dept.setDeptName(bo.getCompanyName()); + if(!ObjectUtil.isEmpty(bo.getDeptId())){ + dept.setParentId(bo.getDeptId()); + SysDept parentDept = deptMapper.selectDeptById(bo.getDeptId()); + String ancestors = parentDept.getAncestors()+","+bo.getDeptId(); + dept.setAncestors(ancestors); + }else{ + dept.setParentId(0L); + dept.setAncestors("0"); + } + dept.setIsTenant("1"); + dept.setCreateTime(date); + dept.setStatus("0"); + dept.setDelFlag("0"); + deptMapper.insertDept(dept); + Long deptId = dept.getDeptId(); + // 角色和部门关联表 + SysRoleDept roleDept = new SysRoleDept(); + roleDept.setRoleId(roleId); + roleDept.setDeptId(deptId); + roleDeptMapper.batchRoleDept(Arrays.asList(roleDept)); + + // 创建系统用户 + SysUser user = new SysUser(); + user.setTenantId(tenantId); + user.setUserName(bo.getUsername()); + user.setNickName(bo.getUsername()); + user.setPassword(BCrypt.hashpw(bo.getPassword())); + user.setDeptId((long) deptId); + user.setCreateTime(date); + user.setUpdateTime(date); + user.setDelFlag("0"); + user.setPhonenumber(bo.getContactPhone()); + user.setStatus("0"); + userMapper.insertUser(user); + //新增系统用户后,默认当前用户为部门的负责人 + SysDept sd = new SysDept(); + sd.setLeader(user.getUserName().toString()); + sd.setDeptId(deptId); + deptMapper.updateDept(sd); + + // 用户和角色关联表 + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(user.getUserId()); + userRole.setRoleId(roleId); + userRoleMapper.batchUserRole(Arrays.asList(userRole)); + return true; + } + + /** + * 生成租户id + * + * @param tenantIds 已有租户id列表 + * @return 租户id + */ + private String generateTenantId(List tenantIds) { + // 随机生成6位 + String numbers = RandomUtil.randomNumbers(6); + // 判断是否存在,如果存在则重新生成 + if (tenantIds.contains(numbers)) { + return generateTenantId(tenantIds); + } + return numbers; + } + + /** + * 根据租户菜单创建租户角色 + * + * @param tenantId 租户编号 + * @param packageId 租户套餐id + * @return 角色id + */ + private Long createTenantRole(String tenantId, Long packageId, String companyName) { + // 获取租户套餐 + SysTenantPackageVo tenantPackageVo = tenantPackageMapper.selectById(packageId); + if (ObjectUtil.isNull(tenantPackageVo)) { + throw new ServiceException("套餐不存在"); + } + // 获取套餐菜单id + List menuIds = StrUtil.split(tenantPackageVo.getMenuIds(), ',') + .stream() + .filter(Objects::nonNull) + .map(Convert::toLong) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // 创建角色 + SysRole role = new SysRole(); + role.setTenantId(tenantId); + role.setRoleName(companyName+ TenantConstants.TENANT_ADMIN_ROLE_NAME); + role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY + "_" + tenantId); + role.setRoleSort(1); + role.setStatus("0"); + roleMapper.insertRole(role); + Long roleId = role.getRoleId(); + + // 创建角色菜单 + List roleMenus = new ArrayList<>(menuIds.size()); + menuIds.forEach(menuId -> { + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(roleId); + roleMenu.setMenuId(menuId); + roleMenus.add(roleMenu); + }); + if(roleMenus.size() > 0) { + roleMenuMapper.batchRoleMenu(roleMenus); + } + + return roleId; + } + + /** + * 修改租户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(SysTenantBo bo) { + LoginUser loginUser = (LoginUser) SecurityUtils.getLoginUser(); + SysTenant tenant = new SysTenant(); + BeanUtil.copyProperties(bo, tenant); + + if(!ObjectUtil.isEmpty(bo.getDeptId())){ //非租户部门 + SysDept currentDept = new SysDept(); + currentDept.setParentId(bo.getDeptId()); + SysDept parentDept = deptMapper.selectDeptById(bo.getDeptId()); + String ancestors = parentDept.getAncestors()+","+bo.getDeptId(); + currentDept.setAncestors(ancestors); + currentDept.setDeptName(bo.getCompanyName()); + deptMapper.updateDeptByTenantId(currentDept, tenant.getTenantId()); + }else{ + List currentDepts = deptMapper.selectByTenantId(tenant.getTenantId()); + SysDept tenantDept = currentDepts.stream().filter(f -> StringUtils.equals(f.getLeader(),"admin")).findFirst().orElse(null); + if(!ObjectUtil.isNull(tenantDept)){ + tenantDept.setDeptName(bo.getCompanyName()); + deptMapper.updateDept(tenantDept); + } + } + SysTenantVo original = sysTenantMapper.queryById(bo.getId()); + if(!ObjectUtil.equal(original.getPackageId(), bo.getPackageId())){ + syncTenantPackage(bo.getTenantId(),bo.getPackageId()); + } + if(!ObjectUtil.equal(original.getCreateDept(), bo.getDeptId())){ + tenant.setCreateDept(bo.getDeptId()); + } + tenant.setCreateDept(bo.getDeptId()); + tenant.setUpdateBy(loginUser.getUserId()+""); + return baseMapper.updateById(tenant) > 0; + } + + public Boolean syncTenantPackage(String tenantId, Long packageId) { + SysTenantPackageVo tenantPackageVO = tenantPackageMapper.selectById(packageId); + List roles = roleMapper.selectRolesByTenantId(tenantId); + List roleIds = new ArrayList<>(roles.size() - 1); + List menuIds = StringUtils.commaStrToLongList(tenantPackageVO.getMenuIds()); + roles.forEach(item -> { + if (item.getRoleKey().contains(TenantConstants.TENANT_ADMIN_ROLE_KEY)) { + List roleMenus = new ArrayList<>(menuIds.size()); + menuIds.forEach(menuId -> { + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(item.getRoleId()); + roleMenu.setMenuId(menuId); + roleMenus.add(roleMenu); + }); + roleMenuMapper.deleteRoleMenuByRoleId(item.getRoleId()); + roleMenuMapper.batchRoleMenu(roleMenus); + } else { + roleIds.add(item.getRoleId()); + } + }); + if (!roleIds.isEmpty()) { + roleMenuMapper.deleteRoleMenuForSync(roleIds, menuIds); + } + return true; + } + + + /** + * 校验租户是否允许操作 + * + * @param tenantId 租户ID + */ + @Override + public void checkTenantAllowed(String tenantId) { + if (ObjectUtil.isNotNull(tenantId) && TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + throw new ServiceException("不允许操作管理租户"); + } + } + + /** + * 批量删除租户 + */ + @Override + public Boolean deleteWithValidByIds(List ids, Boolean isValid) { + if (isValid) { + // 做一些业务上的校验,判断是否需要校验 + if (ids.contains(TenantConstants.SUPER_ADMIN_ID)) { + throw new ServiceException("超管租户不能删除"); + } + } + boolean i = baseMapper.deleteByIds(ids)>0; + List sysDepts = new ArrayList<>(); + for(Long id:ids){ + SysTenantVo sysTenantVo = sysTenantMapper.queryById(id); + if(ObjectUtil.isNotNull(sysTenantVo)){ + List depts = sysDeptMapper.selectByTenantId(sysTenantVo.getTenantId()); + sysDepts.addAll(depts); + } + } + for(SysDept s:sysDepts){ + s.setIsTenant("0"); + sysDeptMapper.updateDept(s); + } + return i; + } + + /** + * 校验企业名称是否唯一 + */ + @Override + public boolean checkCompanyNameUnique(SysTenantBo bo) { + List list = baseMapper.queryByCompanyName(bo.getCompanyName()); + if(StringUtils.isEmpty(bo.getTenantId())){ // 新增 + if(list.size()>0){ + return false; + } + }else{ //修改 + SysTenantVo sysTenantVo = list.stream().filter(item->!bo.getTenantId().equals(item.getTenantId())).findFirst().orElse(null); + if(ObjectUtil.isNotEmpty(sysTenantVo)){ + return false; + } + } + return true; + } + + /** + * 校验联系方式是否唯一 + */ + @Override + public boolean checkPhoneUnique(SysTenantBo bo) { + List list = baseMapper.queryByPhone(bo.getContactPhone()); + if(StringUtils.isEmpty(bo.getTenantId())){ // 新增 + if(list.size()>0){ + return false; + } + }else{ //修改 + SysTenantVo sysTenantVo = list.stream().filter(item->!bo.getTenantId().equals(item.getTenantId())).findFirst().orElse(null); + if(ObjectUtil.isNotEmpty(sysTenantVo)){ + return false; + } + } + return true; + } + + @Override + public boolean checkUsername(SysTenantBo bo) { + SysUser info = userMapper.checkUserNameUnique(bo.getUsername()); + if(StringUtils.isEmpty(bo.getTenantId())){ + if(ObjectUtil.isNotNull(info)){ + return false; + } + }else{ + if(ObjectUtil.isNotNull(info)){ + if(StringUtils.equals(info.getTenantId(),bo.getTenantId())){ + return false; + } + } + } + return true; + } + + + /** + * 校验有效期 + */ + @Override + public boolean checkExpireTime(String tenantId) { + SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId); + // 如果未设置过期时间代表不限制 + if (ObjectUtil.isNull(tenant.getExpireTime())) { + return true; + } + // 如果当前时间在过期时间之前则通过 + return new Date().before(tenant.getExpireTime()); + } + + @Override + public int updateTenantStatus(SysTenantBo bo) { + SysTenant tenant = new SysTenant(); + tenant.setId(bo.getId()); + tenant.setStatus(bo.getStatus()); + LoginUser loginUser = (LoginUser) SecurityUtils.getLoginUser(); + Long userId =loginUser.getUserId(); + SysTenantVo sysTenantVo = baseMapper.queryById(bo.getId()); + SysDept sysDept = new SysDept(); + sysDept.setUpdateBy(userId+""); + sysDept.setStatus(bo.getStatus()); + deptMapper.updateDeptByTenantId(sysDept,sysTenantVo.getTenantId()); + List userIds = sysUserMapper.selectUserIdsByTenantId(sysTenantVo.getTenantId()); + if(CollectionUtil.isNotEmpty(userIds)){ + sysUserMapper.unableUser(userIds,bo.getStatus()); + } + return baseMapper.updateById(tenant); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deptToTenant(SysTenantBo bo) { + Long deptId = bo.getDeptId(); + Date date = new Date(); + LoginUser loginUser = (LoginUser) SecurityUtils.getLoginUser(); + SysTenant add = BeanUtil.toBean(bo, SysTenant.class); + // 获取所有租户编号 + List tenantIds = baseMapper.selectObjs(); + String tenantId = generateTenantId(tenantIds); + add.setTenantId(tenantId); + add.setCreateDept(deptId); + add.setCreateTime(date); + add.setCreateBy(loginUser.getUserId()+""); + add.setStatus("0"); + boolean flag = baseMapper.insert(add) > 0; + if (!flag) { + throw new ServiceException("创建租户失败"); + } + // 根据套餐创建角色 + Long roleId = createTenantRole(tenantId, bo.getPackageId(),bo.getCompanyName()); + + // 角色和部门关联表 + SysRoleDept roleDept = new SysRoleDept(); + roleDept.setRoleId(roleId); + roleDept.setDeptId(deptId); + roleDeptMapper.batchRoleDept(Arrays.asList(roleDept)); + + // 创建系统用户 + SysUser user = new SysUser(); + user.setTenantId(tenantId); + user.setUserName("admin"); + user.setNickName("admin"); + user.setPassword(BCrypt.hashpw("123456")); + user.setDeptId((long) deptId); + user.setCreateTime(date); + user.setUpdateTime(date); + user.setDelFlag("0"); + user.setStatus("0"); + userMapper.insertUser(user); + //新增系统用户后,默认当前用户为部门的负责人 + SysDept sd = new SysDept(); + sd.setLeader(user.getUserName().toString()); + sd.setDeptId(deptId); + sd.setIsTenant("1"); + sd.setTenantId(tenantId); + deptMapper.updateDept(sd); + + List deptIds = deptMapper.selectAllZSByDeptId(deptId); + deptIds.add(deptId); + //更新当前升级为租户的部门下属所有子孙节点的租户ID + deptMapper.updateTenantId(deptIds,tenantId); + //更新当前升级为租户的部门下属所有子孙节点的用户租户ID + userMapper.updateTenantIdOfUsers(deptIds,tenantId); + // 用户和角色关联表 + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(user.getUserId()); + userRole.setRoleId(roleId); + userRoleMapper.batchUserRole(Arrays.asList(userRole)); + return true; + } + +} diff --git a/fp-system/src/main/resources/mapper/SysTenantMapper.xml b/fp-system/src/main/resources/mapper/SysTenantMapper.xml new file mode 100644 index 0000000..db024c8 --- /dev/null +++ b/fp-system/src/main/resources/mapper/SysTenantMapper.xml @@ -0,0 +1,149 @@ + + + + + + + select id,tenant_id tenantId,contact_user_name contactUserName,contact_phone contactPhone,company_name companyName,license_number licenseNumber, + address,intro,domain,remark,status, + package_id packageId,expire_time expireTime,account_count accountCount,del_flag delFlag,create_dept createDept,create_by createBy, + create_time createTime,update_by updateBy,update_time updateTime from sys_tenant + + + + + + + + + + + + + + + + update sys_tenant set del_flag = '1' where id in + + #{id} + + + + + update sys_tenant + + company_name = #{companyName}, + contact_user_name = #{contactUserName}, + contact_phone = #{contactPhone}, + expire_time = #{expireTime}, + account_count = #{accountCount}, + domain = #{domain}, + address = #{address}, + license_number = #{licenseNumber}, + intro = #{intro}, + remark = #{remark}, + status = #{status}, + create_dept = #{createDept}, + package_id = #{packageId}, + update_by = #{updateBy}, + update_time = sysdate() + + where id = #{id} + + + INSERT INTO sys_tenant + + tenant_id, + contact_user_name, + contact_phone, + company_name, + license_number, + address, + intro, + domain, + remark, + package_id, + expire_time, + account_count, + status, + del_flag, + create_dept, + create_by, + create_time, + update_by, + update_time, + + + #{tenantId}, + #{contactUserName}, + #{contactPhone}, + #{companyName}, + #{licenseNumber}, + #{address}, + #{intro}, + #{domain}, + #{remark}, + #{packageId}, + #{expireTime}, + #{accountCount}, + #{status}, + #{delFlag}, + #{createDept}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + + + \ No newline at end of file diff --git a/fp-system/src/main/resources/mapper/SysTenantPackageMapper.xml b/fp-system/src/main/resources/mapper/SysTenantPackageMapper.xml new file mode 100644 index 0000000..55cd353 --- /dev/null +++ b/fp-system/src/main/resources/mapper/SysTenantPackageMapper.xml @@ -0,0 +1,79 @@ + + + + + + + select package_id packageId,package_name packageName,menu_ids menuIds,remark, + menu_check_strictly menuCheckStrictly,status,del_flag delFlag,create_dept createDept,create_by createBy,create_time createTime, + update_by updateBy,update_time updateTime from sys_tenant_package + + + + + + + update sys_tenant_package set del_flag = '1' where package_id in + + #{id} + + + + + update sys_tenant_package + + package_name = #{packageName}, + menu_ids = #{menuIds}, + remark = #{remark}, + menu_check_strictly = #{menuCheckStrictly}, + status = #{status}, + del_flag = #{delFlag}, + create_dept = #{createDept}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + WHERE package_id = #{packageId} + + + INSERT INTO sys_tenant_package + + package_name, + menu_ids, + remark, + menu_check_strictly, + status, + del_flag, + create_dept, + create_by, + create_time, + update_by, + update_time, + + + #{packageName}, + #{menuIds}, + #{remark}, + #{menuCheckStrictly}, + #{status}, + #{delFlag}, + #{createDept}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + \ No newline at end of file diff --git a/fp-system/src/main/resources/mapper/system/SysRoleMapper.xml b/fp-system/src/main/resources/mapper/system/SysRoleMapper.xml index 5627ca0..cac578c 100644 --- a/fp-system/src/main/resources/mapper/system/SysRoleMapper.xml +++ b/fp-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -6,6 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -148,5 +149,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{roleId} + + \ No newline at end of file diff --git a/fp-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/fp-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml index 10c3932..11846e0 100644 --- a/fp-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml +++ b/fp-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml @@ -30,5 +30,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" (#{item.roleId},#{item.menuId}) - + + delete from sys_role_menu where role_id in + + #{roleId} + + + and menu_id not in + + #{menuId} + + + \ No newline at end of file diff --git a/fp-system/src/main/resources/mapper/system/SysUserMapper.xml b/fp-system/src/main/resources/mapper/system/SysUserMapper.xml index 43bc2da..ccc717f 100644 --- a/fp-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/fp-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -6,7 +6,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - + + + @@ -32,6 +34,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -41,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -226,4 +231,29 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + update sys_user set status = #{statusChar} where user_id in + + #{userId} + + + + + + + + update sys_user set tenant_id = #{tenantId} where dept_id in + + #{deptId} + + + + + diff --git a/fp-system/src/main/resources/mapper/system/WxSysDeptMapper.xml b/fp-system/src/main/resources/mapper/system/WxSysDeptMapper.xml index 7627b3e..f13226e 100644 --- a/fp-system/src/main/resources/mapper/system/WxSysDeptMapper.xml +++ b/fp-system/src/main/resources/mapper/system/WxSysDeptMapper.xml @@ -7,6 +7,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -177,4 +179,45 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update sys_dept set del_flag = '2' where dept_id = #{deptId} + + update sys_dept + + parent_id = #{dept.parentId}, + dept_name = #{dept.deptName}, + ancestors = #{dept.ancestors}, + order_num = #{dept.orderNum}, + leader = #{dept.leader}, + phone = #{dept.phone}, + email = #{dept.email}, + status = #{dept.status}, + update_by = #{dept.updateBy}, + is_tenant = #{dept.isTenant}, + update_time = sysdate() + + where tenant_id = #{tenantId,jdbcType=VARCHAR} + + + + + + + + + update sys_dept + set tenant_id = #{tenantId} + where dept_id in + + #{deptId} + + + + diff --git a/pom.xml b/pom.xml index c9995ad..f41916e 100644 --- a/pom.xml +++ b/pom.xml @@ -212,11 +212,19 @@ javase 3.4.1 + - + + + cn.hutool + hutool-all + 5.8.25 + + + fp-admin fp-framework