1、车船模块fix bug
2、运力模块fix bug 3、新增设备台账 4、其他bug 修复 5、调整组织、人员模块
This commit is contained in:
@@ -135,6 +135,17 @@ public class UserController {
|
||||
return R.data(UserWrapper.build().pageVO(pages));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户权限配置客商选项:不应用当前用户的客商数据权限。
|
||||
*/
|
||||
@IsAdmin
|
||||
@GetMapping("/customer-options")
|
||||
@ApiOperationSupport(order = 5)
|
||||
@Operation(summary = "用户客商权限选项", description = "返回当前租户全部客商")
|
||||
public R<List<Map<String, Object>>> customerOptions() {
|
||||
return R.data(userService.selectCustomerOptions(AuthUtil.getTenantId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或修改
|
||||
*/
|
||||
|
||||
@@ -9,9 +9,16 @@
|
||||
<result column="dept_name" property="deptName"/>
|
||||
<result column="full_name" property="fullName"/>
|
||||
<result column="ancestors" property="ancestors"/>
|
||||
<result column="leader_id" property="leaderId"/>
|
||||
<result column="dept_category" property="deptCategory"/>
|
||||
<result column="dept_code" property="deptCode"/>
|
||||
<result column="short_name" property="shortName"/>
|
||||
<result column="pinyin_mnemonic" property="pinyinMnemonic"/>
|
||||
<result column="mnemonic_code" property="mnemonicCode"/>
|
||||
<result column="carrier_customer_id" property="carrierCustomerId"/>
|
||||
<result column="sort" property="sort"/>
|
||||
<result column="remark" property="remark"/>
|
||||
<result column="status" property="status"/>
|
||||
<result column="is_deleted" property="isDeleted"/>
|
||||
</resultMap>
|
||||
|
||||
@@ -21,9 +28,16 @@
|
||||
<result column="dept_name" property="deptName"/>
|
||||
<result column="full_name" property="fullName"/>
|
||||
<result column="ancestors" property="ancestors"/>
|
||||
<result column="leader_id" property="leaderId"/>
|
||||
<result column="dept_category" property="deptCategory"/>
|
||||
<result column="dept_code" property="deptCode"/>
|
||||
<result column="short_name" property="shortName"/>
|
||||
<result column="pinyin_mnemonic" property="pinyinMnemonic"/>
|
||||
<result column="mnemonic_code" property="mnemonicCode"/>
|
||||
<result column="carrier_customer_id" property="carrierCustomerId"/>
|
||||
<result column="sort" property="sort"/>
|
||||
<result column="remark" property="remark"/>
|
||||
<result column="status" property="status"/>
|
||||
<result column="is_deleted" property="isDeleted"/>
|
||||
<result column="has_children" property="hasChildren"/>
|
||||
</resultMap>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springblade.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springblade.system.pojo.entity.UserCustomerScope;
|
||||
|
||||
public interface UserCustomerScopeMapper extends BaseMapper<UserCustomerScope> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springblade.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springblade.system.pojo.entity.UserDataScope;
|
||||
|
||||
public interface UserDataScopeMapper extends BaseMapper<UserDataScope> {
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import org.springblade.system.pojo.entity.User;
|
||||
import org.springblade.system.excel.UserExcel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mapper 接口
|
||||
@@ -78,4 +79,6 @@ public interface UserMapper extends BaseMapper<User> {
|
||||
*/
|
||||
List<UserExcel> exportUser(@Param("ew") Wrapper<User> queryWrapper);
|
||||
|
||||
List<Map<String, Object>> selectCustomerOptions(@Param("tenantId") String tenantId);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,30 +25,41 @@
|
||||
<result column="role_id" property="roleId"/>
|
||||
<result column="dept_id" property="deptId"/>
|
||||
<result column="post_id" property="postId"/>
|
||||
<result column="remark" property="remark"/>
|
||||
<result column="oa_person_id" property="oaPersonId"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectUserPage" resultMap="userResultMap">
|
||||
select * from blade_user where is_deleted = 0
|
||||
select bu.*, (
|
||||
select max(bud.oa_id)
|
||||
from blade_user_dept bud
|
||||
where bud.user_id = bu.id and bud.is_deleted = 0
|
||||
) as oa_person_id
|
||||
from blade_user bu
|
||||
where bu.is_deleted = 0
|
||||
<if test="tenantId!=null and tenantId != ''">
|
||||
and tenant_id = #{tenantId}
|
||||
and bu.tenant_id = #{tenantId}
|
||||
</if>
|
||||
<if test="user.tenantId!=null and user.tenantId != ''">
|
||||
and tenant_id = #{user.tenantId}
|
||||
and bu.tenant_id = #{user.tenantId}
|
||||
</if>
|
||||
<if test="user.account!=null and user.account != ''">
|
||||
and account = #{user.account}
|
||||
and bu.account = #{user.account}
|
||||
</if>
|
||||
<if test="user.realName!=null and user.realName != ''">
|
||||
and real_name = #{user.realName}
|
||||
and bu.real_name = #{user.realName}
|
||||
</if>
|
||||
<if test="user.phone!=null and user.phone != ''">
|
||||
and bu.phone = #{user.phone}
|
||||
</if>
|
||||
<if test="user.userType!=null and user.userType != ''">
|
||||
and user_type = #{user.userType}
|
||||
and bu.user_type = #{user.userType}
|
||||
</if>
|
||||
<if test="user.status!=null and user.status>=0">
|
||||
and status = #{user.status}
|
||||
and bu.status = #{user.status}
|
||||
</if>
|
||||
<if test="deptIdList!=null and deptIdList.size>0">
|
||||
and id in (
|
||||
and bu.id in (
|
||||
SELECT
|
||||
user_id
|
||||
FROM
|
||||
@@ -60,7 +71,7 @@
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
ORDER BY id
|
||||
ORDER BY bu.id
|
||||
</select>
|
||||
|
||||
<select id="getUser" resultMap="userResultMap">
|
||||
@@ -87,4 +98,13 @@
|
||||
SELECT id, tenant_id, user_type, account, name, real_name, email, phone, birthday, role_id, dept_id, post_id FROM blade_user ${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectCustomerOptions" resultType="java.util.HashMap">
|
||||
SELECT id, customer_code AS customerCode, full_name AS fullName, short_name AS shortName,
|
||||
customer_type AS customerType, status, approval_status AS approvalStatus
|
||||
FROM blade_customer_archive
|
||||
WHERE tenant_id = #{tenantId}
|
||||
AND is_deleted = 0
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -105,6 +105,9 @@ public interface IUserService extends BaseService<User> {
|
||||
*/
|
||||
IPage<User> selectUserPage(IPage<User> page, User user, Long deptId, String tenantId);
|
||||
|
||||
/** 用户权限配置使用的当前租户全量客商选项。 */
|
||||
List<Map<String, Object>> selectCustomerOptions(String tenantId);
|
||||
|
||||
/**
|
||||
* 自定义用户搜索分页(按姓名 / 部门 / 岗位模糊匹配,限定当前会话租户)
|
||||
*
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springblade.core.tenant.TenantGuard.EntityType.DEPT;
|
||||
@@ -189,6 +190,11 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
List<Long> idList = Func.toLongList(ids);
|
||||
// 租户守卫:批量校验目标部门全部归属当前会话租户
|
||||
TenantGuard.verifyBatch(this, idList, DEPT);
|
||||
boolean containsRootDept = listByIds(idList).stream()
|
||||
.anyMatch(dept -> BladeConstant.TOP_PARENT_ID.equals(dept.getParentId()));
|
||||
if (containsRootDept) {
|
||||
throw new ServiceException("根节点不能删除!");
|
||||
}
|
||||
Long cnt = baseMapper.selectCount(Wrappers.<Dept>query().lambda().in(Dept::getParentId, idList));
|
||||
if (cnt > 0L) {
|
||||
throw new ServiceException("请先删除子节点!");
|
||||
@@ -200,6 +206,7 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean submit(Dept dept) {
|
||||
Long parentId = dept.getParentId();
|
||||
Dept parent = null;
|
||||
// 顶级语义:parentId 为 null 或 TOP_PARENT_ID (0L) 均视为顶级部门
|
||||
if (parentId == null || parentId.equals(BladeConstant.TOP_PARENT_ID)) {
|
||||
// 顶级部门:租户守卫统一处理新增 / 修改路径的租户绑定
|
||||
@@ -213,7 +220,7 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
}
|
||||
Dept self = Func.isNotEmpty(dept.getId())
|
||||
? TenantGuard.verify(this, dept.getId(), DEPT) : null;
|
||||
Dept parent = TenantGuard.verify(this, dept.getParentId(), DEPT_PARENT);
|
||||
parent = TenantGuard.verify(this, dept.getParentId(), DEPT_PARENT);
|
||||
if (parent == null) {
|
||||
throw new ServiceException("上级部门不存在!");
|
||||
}
|
||||
@@ -228,9 +235,59 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
if (Func.isEmpty(dept.getTenantId())) {
|
||||
throw new ServiceException("租户ID不能为空");
|
||||
}
|
||||
validateDeptCategory(dept, parent);
|
||||
validateDeptCode(dept, parent);
|
||||
return saveOrUpdate(dept);
|
||||
}
|
||||
|
||||
private void validateDeptCategory(Dept dept, Dept parent) {
|
||||
if (parent == null) {
|
||||
throw new ServiceException("请选择上级组织");
|
||||
}
|
||||
List<Integer> allowedCategories;
|
||||
if (BladeConstant.TOP_PARENT_ID.equals(parent.getParentId())) {
|
||||
allowedCategories = "外部组织".equals(parent.getDeptName()) ? List.of(6) : List.of(1);
|
||||
} else if (Integer.valueOf(1).equals(parent.getDeptCategory())) {
|
||||
allowedCategories = List.of(2, 3);
|
||||
} else if (List.of(2, 3).contains(parent.getDeptCategory())) {
|
||||
allowedCategories = List.of(4, 5, 6);
|
||||
} else {
|
||||
throw new ServiceException("上级组织层级不支持新增下级组织");
|
||||
}
|
||||
if (!allowedCategories.contains(dept.getDeptCategory())) {
|
||||
throw new ServiceException("组织类型不符合上级组织层级规则");
|
||||
}
|
||||
if (Integer.valueOf(6).equals(dept.getDeptCategory()) && Func.isEmpty(dept.getCarrierCustomerId())) {
|
||||
throw new ServiceException("请选择承运商");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDeptCode(Dept dept, Dept parent) {
|
||||
String deptCode = dept.getDeptCode();
|
||||
if (StringUtil.isBlank(deptCode)) {
|
||||
throw new ServiceException("组织编码不能为空");
|
||||
}
|
||||
deptCode = deptCode.trim();
|
||||
if (deptCode.length() > 30) {
|
||||
throw new ServiceException("组织编码不能超过30个字符");
|
||||
}
|
||||
if (parent == null || StringUtil.isBlank(parent.getDeptCode())) {
|
||||
throw new ServiceException("请选择已配置组织编码的上级组织");
|
||||
}
|
||||
String pattern = Pattern.quote(parent.getDeptCode()) + "-\\d+";
|
||||
if (!deptCode.matches(pattern)) {
|
||||
throw new ServiceException("组织编码格式应为:上级编码-分段数字");
|
||||
}
|
||||
LambdaQueryWrapper<Dept> queryWrapper = Wrappers.<Dept>lambdaQuery().eq(Dept::getDeptCode, deptCode);
|
||||
if (Func.isNotEmpty(dept.getId())) {
|
||||
queryWrapper.ne(Dept::getId, dept.getId());
|
||||
}
|
||||
if (baseMapper.selectCount(queryWrapper) > 0) {
|
||||
throw new ServiceException("组织编码已存在");
|
||||
}
|
||||
dept.setDeptCode(deptCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeptVO> search(String deptName, Long parentId) {
|
||||
String tenantId = AuthUtil.getTenantId();
|
||||
|
||||
@@ -56,6 +56,8 @@ import org.springblade.system.cache.SysCache;
|
||||
import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.system.excel.UserExcel;
|
||||
import org.springblade.system.mapper.UserMapper;
|
||||
import org.springblade.system.mapper.UserDataScopeMapper;
|
||||
import org.springblade.system.mapper.UserCustomerScopeMapper;
|
||||
import org.springblade.system.pojo.context.IPhone;
|
||||
import org.springblade.system.pojo.entity.*;
|
||||
import org.springblade.system.pojo.enums.DictEnum;
|
||||
@@ -95,6 +97,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
|
||||
|
||||
private final IUserDeptService userDeptService;
|
||||
private final UserDataScopeMapper userDataScopeMapper;
|
||||
private final UserCustomerScopeMapper userCustomerScopeMapper;
|
||||
private final IUserOauthService userOauthService;
|
||||
private final IRoleService roleService;
|
||||
private final BladeTenantProperties tenantProperties;
|
||||
@@ -106,7 +110,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
public User getDetail(User user) {
|
||||
QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user);
|
||||
applyTenantScope(queryWrapper);
|
||||
return getOne(queryWrapper);
|
||||
return fillUserScopes(getOne(queryWrapper));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,6 +124,10 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean submit(User user) {
|
||||
bindSessionTenant(user);
|
||||
if (user.getUserType() == null) {
|
||||
user.setUserType(UserType.WEB.getCategory());
|
||||
}
|
||||
applyUserDefaults(user);
|
||||
return saveUser(user);
|
||||
}
|
||||
|
||||
@@ -148,7 +156,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
throw new ServiceException(StringUtil.format("当前手机 [{}] 已存在!", user.getPhone()));
|
||||
}
|
||||
CacheUtil.clear(USER_CACHE);
|
||||
return submitUserInfo(user) && submitUserDept(user);
|
||||
applyUserDefaults(user);
|
||||
return submitUserInfo(user) && submitUserDept(user) && submitUserScopes(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,6 +207,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
return page.setRecords(baseMapper.selectUserPage(page, user, deptIdList, tenantId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> selectCustomerOptions(String tenantId) {
|
||||
return baseMapper.selectCustomerOptions(tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<UserVO> selectUserSearch(UserVO user, Query query) {
|
||||
LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>query().lambda();
|
||||
@@ -676,7 +690,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
? Func.toStrWithEmpty(tenantId, AuthUtil.getTenantId())
|
||||
: AuthUtil.getTenantId();
|
||||
LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>query().lambda()
|
||||
.select(User::getId, User::getRealName)
|
||||
.select(User::getId, User::getRealName, User::getPhone)
|
||||
.like(StringUtil.isNoneBlank(realName), User::getRealName, realName)
|
||||
.eq(User::getTenantId, resolvedTenantId)
|
||||
.eq(User::getIsLeader, BladeConstant.DB_STATUS_1)
|
||||
@@ -756,9 +770,10 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
throw new ServiceException("当前租户已到最大账号额度!");
|
||||
}
|
||||
}
|
||||
if (Func.isNotEmpty(user.getPassword())) {
|
||||
user.setPassword(DigestUtil.encrypt(user.getPassword()));
|
||||
if (Func.isEmpty(user.getPassword())) {
|
||||
user.setPassword(ParamCache.getValue(DEFAULT_PARAM_PASSWORD));
|
||||
}
|
||||
user.setPassword(DigestUtil.encrypt(user.getPassword()));
|
||||
Long userCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, tenantId).eq(User::getAccount, user.getAccount()));
|
||||
if (userCount > 0L && Func.isEmpty(user.getId())) {
|
||||
throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount()));
|
||||
@@ -768,7 +783,45 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
||||
throw new ServiceException(StringUtil.format("当前手机 [{}] 已存在!", user.getPhone()));
|
||||
}
|
||||
CacheUtil.clear(USER_CACHE);
|
||||
return save(user) && submitUserDept(user);
|
||||
return save(user) && submitUserDept(user) && submitUserScopes(user);
|
||||
}
|
||||
|
||||
private void applyUserDefaults(User user) {
|
||||
if (user.getPersonCategory() == null) user.setPersonCategory(1);
|
||||
if (user.getDataScopeRange() == null) user.setDataScopeRange(1);
|
||||
if (user.getDataLevelRange() == null) user.setDataLevelRange(1);
|
||||
if (user.getIncludeNewCustomer() == null) user.setIncludeNewCustomer(0);
|
||||
}
|
||||
|
||||
private boolean submitUserScopes(User user) {
|
||||
userDataScopeMapper.delete(Wrappers.<UserDataScope>lambdaQuery().eq(UserDataScope::getUserId, user.getId()));
|
||||
userCustomerScopeMapper.delete(Wrappers.<UserCustomerScope>lambdaQuery().eq(UserCustomerScope::getUserId, user.getId()));
|
||||
if (Objects.equals(user.getDataScopeRange(), 3) && user.getDataScopeDeptIds() != null) {
|
||||
user.getDataScopeDeptIds().forEach(deptId -> {
|
||||
UserDataScope scope = new UserDataScope();
|
||||
scope.setUserId(user.getId());
|
||||
scope.setDeptId(deptId);
|
||||
userDataScopeMapper.insert(scope);
|
||||
});
|
||||
}
|
||||
if (user.getCustomerIds() != null) {
|
||||
user.getCustomerIds().forEach(customerId -> {
|
||||
UserCustomerScope scope = new UserCustomerScope();
|
||||
scope.setUserId(user.getId());
|
||||
scope.setCustomerId(customerId);
|
||||
userCustomerScopeMapper.insert(scope);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private User fillUserScopes(User user) {
|
||||
if (user == null || user.getId() == null) return user;
|
||||
user.setDataScopeDeptIds(userDataScopeMapper.selectList(Wrappers.<UserDataScope>lambdaQuery()
|
||||
.eq(UserDataScope::getUserId, user.getId())).stream().map(UserDataScope::getDeptId).toList());
|
||||
user.setCustomerIds(userCustomerScopeMapper.selectList(Wrappers.<UserCustomerScope>lambdaQuery()
|
||||
.eq(UserCustomerScope::getUserId, user.getId())).stream().map(UserCustomerScope::getCustomerId).toList());
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user