修改菜单表:sys_permission, 增加一个字段tenant_id(租户ID),并且设置tenant_id的初始值。
ALTER TABLE `sys_permission`
ADD COLUMN `tenant_id` int(5) NULL COMMENT '租户ID' AFTER `internal_or_external`;
update sys_permission set tenant_id = 1;
修改org.jeecg.modules.system.entity.SysPermission,增加tenantId属性。如下: ```java /**
- 外链菜单打开方式 0/内部打开 1/外部打开 / private boolean internalOrExternal; /update_end author:wuxianquan date:20190908 for:实体增加字段 */
/**
- 租户id */ private Integer tenantId; ```
修改部门表: sys_depart,增加一个字段tenant_id(租户ID),并且设置tenant_id的初始值。
ALTER TABLE `sys_depart`
ADD COLUMN `tenant_id` int(5) NULL COMMENT '租户ID' AFTER `update_time`;
update sys_depart set tenant_id = 1;
修改org.jeecg.modules.system.entity.SysDepart,增加tenantId属性。如下: ```java
/**
- 租户id */ private Integer tenantId;
5. 修改角色表:sys_role,增加一个字段tenant_id(租户ID),并且设置tenant_id的初始值。
```sql
ALTER TABLE `sys_role`
ADD COLUMN `tenant_id` int(1) NULL COMMENT '租户ID' AFTER `update_time`;
update sys_role set tenant_id = 1;
- 修改org.jeecg.modules.system.entity.SysRole,增加tenantId属性。如下:
```java
/**
- 租户id */ private Integer tenantId;
7. 修改代码:全项目搜索注解@RequiresRoles @RequiresPermissions,删除,没找到忽略。自己新增的业务模块,如果用到了这两个注解,可以参考使用。这里只是去除系统功能模块中的注解。3.0版本其实已经都删除了。
7. 修改SysDepartMapper.xml,增加“根据父ID查询同级部门”的代码。
```xml
<!-- 根据父ID查询同级部门 -->
<select id="querySameLevelDepart" parameterType="String" resultType="org.jeecg.modules.system.entity.SysDepart">
select * from sys_depart
<choose>
<when test="pid != null and pid != ''">
where parent_id = #{pid,jdbcType=VARCHAR}
</when>
<otherwise>
where parent_id is null or parent_id=''
</otherwise>
</choose>
order by org_code desc
</select>
<!-- 根据username查询所拥有的部门 -->
- 修改org.jeecg.modules.system.mapper.SysDepartMapper,增加代码:
```java
/**
- 根据父ID查询同级部门 *
- @param pid
- @return
*/
@InterceptorIgnore(tenantLine = “true”)
List
querySameLevelDepart(@Param(“pid”) String pid);
10. 接口org.jeecg.modules.system.service.ISysDepartService新增代码如下:
```java
/**
* 根据父ID查询同级部门
*
* @param pid
* @return
*/
List<SysDepart> querySameLevelDepart(String pid);
- 实现类org.jeecg.modules.system.service.impl.SysDepartServiceImpl新增:
```java
/**
- 根据父ID查询同级部门 *
- @param pid
- @return
*/
@Override
public List
querySameLevelDepart(String pid) { return baseMapper.querySameLevelDepart(pid); }
12. 修改org.jeecg.modules.system.service.impl.SysDepartServiceImpl
将注解@Cacheable(value = CacheConstant.SYS_DEPARTS_CACHE) @Cacheable(value = CacheConstant.SYS_DEPART_IDS_CACHE)去掉
13. 修改org.jeecg.modules.system.model.SysPermissionTree代码
```java
/**
* 租户ID
*/
private java.lang.Integer tenantId;
public Integer getTenantId() {
return tenantId;
}
public void setTenantId(Integer tenantId) {
this.tenantId = tenantId;
}
修改OrgCodeRule代码,原来的代码如下:
if (StringUtil.isNullOrEmpty(parentId)) {
// 线判断数据库中的表是否为空,空则直接返回初始编码
query1.eq(SysDepart::getParentId, "").or().isNull(SysDepart::getParentId);
query1.orderByDesc(SysDepart::getOrgCode);
departList = sysDepartService.list(query1);
if (departList == null || departList.size() == 0) {
strArray[0] = YouBianCodeUtil.getNextYouBianCode(null);
strArray[1] = "1";
return strArray;
} else {
SysDepart depart = departList.get(0);
oldOrgCode = depart.getOrgCode();
orgType = depart.getOrgType();
newOrgCode = YouBianCodeUtil.getNextYouBianCode(oldOrgCode);
}
} else {//反之则查询出所有同级的部门,获取结果后有两种情况,有同级和没有同级
// 封装查询同级的条件
query.eq(SysDepart::getParentId, parentId);
// 降序排序
query.orderByDesc(SysDepart::getOrgCode);
// 查询出同级部门的集合
List<SysDepart> parentList = sysDepartService.list(query);
// 查询出父级部门
SysDepart depart = sysDepartService.getById(parentId);
// 获取父级部门的Code
String parentCode = depart.getOrgCode();
// 根据父级部门类型算出当前部门的类型
orgType = String.valueOf(Integer.valueOf(depart.getOrgType()) + 1);
// 处理同级部门为null的情况
if (parentList == null || parentList.size() == 0) {
// 直接生成当前的部门编码并返回
newOrgCode = YouBianCodeUtil.getSubYouBianCode(parentCode, null);
} else { //处理有同级部门的情况
// 获取同级部门的编码,利用工具类
String subCode = parentList.get(0).getOrgCode();
// 返回生成的当前部门编码
newOrgCode = YouBianCodeUtil.getSubYouBianCode(parentCode, subCode);
}
}
修改后的代码如下:
//如果是最高级,则查询出同级的org_code, 调用工具类生成编码并返回
if (StringUtil.isNullOrEmpty(parentId)) {
// 线判断数据库中的表是否为空,空则直接返回初始编码
//query1.eq(SysDepart::getParentId, "").or().isNull(SysDepart::getParentId);
//query1.orderByDesc(SysDepart::getOrgCode);
//departList = sysDepartService.list(query1);
departList = sysDepartService.querySameLevelDepart(parentId);
if (departList == null || departList.size() == 0) {
strArray[0] = YouBianCodeUtil.getNextYouBianCode(null);
strArray[1] = "1";
return strArray;
} else {
SysDepart depart = departList.get(0);
oldOrgCode = depart.getOrgCode();
orgType = depart.getOrgType();
newOrgCode = YouBianCodeUtil.getNextYouBianCode(oldOrgCode);
}
} else {//反之则查询出所有同级的部门,获取结果后有两种情况,有同级和没有同级
// 封装查询同级的条件
//query.eq(SysDepart::getParentId, parentId);
// 降序排序
//query.orderByDesc(SysDepart::getOrgCode);
// 查询出同级部门的集合
//List<SysDepart> parentList = sysDepartService.list(query);
List<SysDepart> parentList = sysDepartService.querySameLevelDepart(parentId);
// 查询出父级部门
SysDepart depart = sysDepartService.getById(parentId);
// 获取父级部门的Code
String parentCode = depart.getOrgCode();
// 根据父级部门类型算出当前部门的类型
orgType = String.valueOf(Integer.valueOf(depart.getOrgType()) + 1);
// 处理同级部门为null的情况
if (parentList == null || parentList.size() == 0) {
// 直接生成当前的部门编码并返回
newOrgCode = YouBianCodeUtil.getSubYouBianCode(parentCode, null);
} else { //处理有同级部门的情况
// 获取同级部门的编码,利用工具类
String subCode = parentList.get(0).getOrgCode();
// 返回生成的当前部门编码
newOrgCode = YouBianCodeUtil.getSubYouBianCode(parentCode, subCode);
}
}
修改租户表:sys_tenant 增加一个字段 pre_code(角色编码前缀)
``sql ALTER TABLE
sys_tenantADD COLUMN
pre_codevarchar(100) NULL COMMENT '角色编码前缀' AFTER
status`; alter table sys_tenant add constraint sys_tenant_pre_code_uindexprimary key (pre_code);
16. 修改org.jeecg.modules.system.entity.SysTenant,增加如下内容:
```java
/**
* 角色编码前缀
*/
private String preCode;
修改新增租户的逻辑。
租户接口org.jeecg.modules.system.service.ISysTenantService: ```java /**
- 保存
- @param sysTenant */ void saveSysTenant(SysTenant sysTenant);
18. 修改sys_permission表。增加base_flag字段,base_flag用来设置基础菜单标志,0-不可复制,1-可复制;默认 0
```sql
ALTER TABLE `sys_permission`
ADD COLUMN `base_flag` int(1) default 0 not NULL COMMENT '基础菜单标志' AFTER `tenant_id`;
update sys_permission set base_flag = 0;
- 手动修改sys_permission表,找出需要复制给其他租户的菜单数据,把这些菜单的base_flag字段设置成1。
修改org.jeecg.modules.system.entity.SysPermission,增加baseFlag属性。如下: ```java /**
- 租户id */ private Integer tenantId;
/**
- 设置基础菜单标志,0-不可复制,1-可复制;默认 0
- 创建新租户时,复制baseFlag为1的菜单为新租户可用。 */ private Integer baseFlag;
21. 修改org.jeecg.modules.system.controller.SysTenantController。add方法修改如下:
```java
/**
* 添加
* @param
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysTenant> add(@RequestBody SysTenant sysTenant) {
Result<SysTenant> result = new Result();
if(sysTenantService.getById(sysTenant.getId())!=null){
return result.error500("该编号已存在!");
}
LambdaQueryWrapper<SysTenant> query = new LambdaQueryWrapper<SysTenant>();
query.eq(SysTenant::getPreCode, sysTenant.getPreCode());
if(sysTenantService.count(query) > 0){
return result.error500("该角色前缀编号已存在!");
}
try {
//sysTenantService.save(sysTenant);
sysTenantService.saveSysTenant(sysTenant);
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(), e);
result.error500("操作失败");
}
return result;
}
- 实现类org.jeecg.modules.system.service.impl.SysTenantServiceImpl,增加如下方法: ```java package org.jeecg.modules.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.util.oConvertUtils; import org.jeecg.modules.system.entity.; import org.jeecg.modules.system.mapper.SysTenantMapper; import org.jeecg.modules.system.service.; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable; import java.util.*;
@Service(“sysTenantServiceImpl”)
@Slf4j
public class SysTenantServiceImpl extends ServiceImpl
@Autowired ISysPermissionService sysPermissionService;
@Autowired ISysUserService sysUserService;
@Autowired ISysRoleService sysRoleService;
@Autowired ISysUserRoleService sysUserRoleService;
@Autowired ISysRolePermissionService sysRolePermissionService;
@Override
public List
@Override
public int countUserLinkTenant(String id) {
LambdaQueryWrapper
@Override public boolean removeTenantById(String id) { // 查找出已被关联的用户数量 int userCount = this.countUserLinkTenant(id); if (userCount > 0) { throw new JeecgBootException(“该租户已被引用,无法删除!”); } return this.removeById(id); }
@Override public boolean removeById(Serializable id) { return super.removeById(id); }
@Override public boolean save(SysTenant entity) { return super.save(entity); }
/**
- 保存 *
@param sysTenant */ @Override @Transactional public void saveSysTenant(SysTenant sysTenant) { this.save(sysTenant); int tenantId = sysTenant.getId(); List
ls = getPermissionList(); Collection menuIds = setPermissionTenant(ls, tenantId); sysPermissionService.saveBatch(ls); // 修改admin用户的租户 SysUser user = sysUserService.getUserByName(“admin”); String refTenantIds = user.getRelTenantIds(); if (oConvertUtils.isEmpty(refTenantIds)) { user.setRelTenantIds(String.valueOf(tenantId)); } else { user.setRelTenantIds(refTenantIds + “,” + tenantId); } sysUserService.updateById(user);
// 添加admin角色 SysRole role = new SysRole(); role.setRoleCode(sysTenant.getPreCode() + “_admin”); role.setRoleName(“管理员”); role.setTenantId(tenantId); sysRoleService.save(role);
// 添加角色 用户关系—给admin管理员绑定新创建的租户角色 SysUserRole sysUserRole = new SysUserRole(); // TODO is ok? sysUserRole.setRoleId(role.getId()); sysUserRole.setUserId(user.getId()); sysUserRoleService.save(sysUserRole);
// 添加角色 菜单关系 List
list = new ArrayList<>(); for (String menuId : menuIds) { SysRolePermission sp = new SysRolePermission(); sp.setPermissionId(menuId); sp.setRoleId(role.getId()); list.add(sp); } sysRolePermissionService.saveBatch(list); }
private List
private String randomId() { long id = IdWorker.getId(); return String.valueOf(id); }
private Collection
}
23. 修改租户前端界面TenantForm.vue,在租户编号后面增加“角色编码前缀”输入框。
```javascript
<a-col :span="24">
<a-form-model-item label="租户编号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="id">
<a-input-number style="width: 100%" :min="1" v-model="model.id" placeholder="请输入租户编号" :disabled="disabledId"></a-input-number>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="角色编码前缀" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="preCode">
<a-input style="width: 100%" v-model="model.preCode" placeholder="请输入角色编码前缀"></a-input>
</a-form-model-item>
</a-col>
- 租户前端界面TenantList.vue,在租户编号后面增加“角色编码前缀”,如下:
```javascript
{
title:'租户编号',
align:"center",
dataIndex: 'id'
},
{
title:'角色编码前缀',
align:"center",
dataIndex: 'preCode'
},
25. 修改org.jeecg.config.mybatis.MybatisPlusSaasConfig,增加角色、菜单、部门的表名加入tenantTable列表。
```java
static {
tenantTable.add("demo");
//角色、菜单、部门
tenantTable.add("sys_role");
tenantTable.add("sys_permission");
tenantTable.add("sys_depart");
}
注意:
系统做成多租户后,新增租户的时候菜单会复制多份,如果这个时候想再切回来,那么多余的数据需要被清除,可以执行下面的sql:
delete from sys_role_permission where permission_id in (select id from sys_permission where tenant_id <> 1);
delete from sys_role_permission where role_id in (select id from sys_role where tenant_id <> 1);
delete from sys_permission where tenant_id <> 1;
delete from sys_user_role where role_id in (select id from sys_role where tenant_id <> 1);
delete from sys_role where tenant_id <> 1;
delete from sys_user_depart where dep_id in (select id from sys_depart where tenant_id <> 1);
delete from sys_depart where tenant_id <> 1;
此番修改后,原系统中的管理员角色和管理员都属于id为1的租户。新建租户的时候会把租户1的管理员赋予新租户。同时系统会给新租户创建一个管理员角色,名字用preCode+admin的方式生成。