Selaa lähdekoodia

fix(api): 优化后台管理相关接口功能及导入客户数据支持

- AdminUserGroupController的userAdd接口返回新增ID
- 修复SysUserGroupRelationService中群组用户角色更新逻辑
- SysUserRoleRelationService同步更新用户角色,简化异步调用
- SysGroupService新增分组编辑时的关联数据校验,防止误删
- 优化SysCustomerFollowAuditService中审核相关数据库操作逻辑
- 添加CustomerDataPublicController中客户数据Excel导入功能及数据校验
- 新增DictCityRegionService根据父级代码查询城市列表接口
- 修正日志配置logback-spring.xml的conversionRule class属性
- 审核及参数服务中注释历史依赖逻辑,保留代码方便后续扩展
- 多处方法增加事务注解确保数据操作一致性
- 优化后台用户编辑时对分组关联的修改限制及异常提示
- 更新pom.xml引入EasyExcel依赖支持Excel处理功能
zhangxf 1 kuukausi sitten
vanhempi
commit
52d880b80a

+ 18 - 0
pom.xml

@@ -157,6 +157,24 @@
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
         </dependency>
+
+
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-spring-boot-starter</artifactId>
+            <version>4.1.3</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-annotation</artifactId>
+            <version>4.1.3</version>
+        </dependency>
+        <!-- 引入EasyExcel -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>3.3.2</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 4 - 7
src/main/java/com/jtzx/crm/module/api/web/sys/AdminUserGroupController.java

@@ -59,10 +59,10 @@ public class AdminUserGroupController {
 
     @Operation(summary = "设置分组用户数据接口")
     @PostMapping(value = "/group/userAdd")
-    public ApiResult<Void> userAdd(@RequestBody AdminSysUserGroupRelationDTO dto) {
+    public ApiResult<Long> userAdd(@RequestBody AdminSysUserGroupRelationDTO dto) {
         sysCustomerDataPermissionService.adminPermission();
-        sysUserGroupRelationService.adminInsert(dto);
-        return ApiResult.success();
+        Long id = sysUserGroupRelationService.adminInsert(dto);
+        return ApiResult.data(id);
     }
 
     @Operation(summary = "删除分组用户数据接口")
@@ -73,9 +73,6 @@ public class AdminUserGroupController {
         return ApiResult.success();
     }
 
-
-
-
     @Operation(summary = "列表分页查询接口")
     @GetMapping(value = "/group/pageListData")
     public ApiResult<PageResult<SysUserGroupRelationPageListBO>> queryListByPage(AdminSysUserGroupRelationDTO dto) {
@@ -123,7 +120,7 @@ public class AdminUserGroupController {
     @PostMapping(value = "/group/manager/groupSort")
     public ApiResult<Void> groupSort(@RequestBody List<AdminSysGroupInsertOrUpdateDTO> dtoList) {
         sysCustomerDataPermissionService.adminPermission();
-        if(CollUtil.isEmpty(dtoList)){
+        if (CollUtil.isEmpty(dtoList)) {
             throw new BusinessException(400, "参数不能为空");
         }
         dtoList.forEach(sysGroupService::adminUpdate);

+ 128 - 0
src/main/java/com/jtzx/crm/module/api/web/sys/CustomerDataPublicController.java

@@ -1,21 +1,33 @@
 package com.jtzx.crm.module.api.web.sys;
 
 
+import cc.uncarbon.framework.core.exception.BusinessException;
 import cc.uncarbon.framework.core.page.PageResult;
 import cc.uncarbon.framework.web.model.response.ApiResult;
 import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.hutool.core.collection.CollUtil;
+import com.alibaba.excel.EasyExcel;
+import com.google.common.collect.Lists;
 import com.jtzx.crm.module.api.constant.ApiConstant;
 import com.jtzx.crm.module.api.util.CrmAdminStpUtil;
+import com.jtzx.crm.module.sys.entity.SysParamBaseDataEntity;
 import com.jtzx.crm.module.sys.model.request.*;
 import com.jtzx.crm.module.sys.model.response.*;
+import com.jtzx.crm.module.sys.service.DictCityRegionService;
+import com.jtzx.crm.module.sys.service.DictProvinceRegionService;
 import com.jtzx.crm.module.sys.service.SysCustomerDataPublicService;
+import com.jtzx.crm.module.sys.service.SysCustomerUserCommonService;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.validation.Valid;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.InputStream;
+import java.util.LinkedHashMap;
 import java.util.List;
 
 @SaCheckLogin(type = CrmAdminStpUtil.TYPE)
@@ -28,6 +40,11 @@ public class CustomerDataPublicController {
 
     private final SysCustomerDataPublicService sysCustomerDataPublicService;
 
+    private final SysCustomerUserCommonService sysCustomerUserCommonService;
+
+    private final DictProvinceRegionService dictProvinceRegionService;
+
+    private final DictCityRegionService dictCityRegionService;
 
     @Operation(summary = "查询顶部筛选条件信息接口")
     @GetMapping(value = "/head/select/data")
@@ -114,4 +131,115 @@ public class CustomerDataPublicController {
         SysCustomerOperLogDataBO result = sysCustomerDataPublicService.queryOperLogData(dto);
         return ApiResult.data(result);
     }
+
+
+    @Operation(summary = "导入客户数据接口")
+    @PostMapping(value = "/importCustomerData")
+    public ApiResult<Void> importCustomerData(@Parameter(description = "文件参数") @RequestPart MultipartFile file) {
+        this.handleImportCustomerData(file);
+        return ApiResult.success();
+    }
+
+    /**
+     * 处理导入客户数据
+     *
+     * @param file
+     */
+    public void handleImportCustomerData(MultipartFile file) {
+        try {
+            InputStream inputStream = file.getInputStream();
+            List<LinkedHashMap<Integer, Object>> allData = EasyExcel.read(inputStream)
+                    .sheet(0)
+                    .headRowNumber(0)
+                    .doReadSync();
+            // 验证数据,除标题外的行不能为空
+            if (allData == null || allData.size() < 2) {
+                throw new BusinessException("excel数据异常,导入失败");
+            }
+            //组装数据
+            List<AdminSysCustomerDataInsertOrUpdateDTO> dtoList = this.getDTOList(allData);
+            if (CollUtil.isEmpty(dtoList)) {
+                throw new BusinessException("excel数据异常,导入失败");
+            }
+            //批量插入数据
+            dtoList.forEach(sysCustomerDataPublicService::adminInsertCustomerData);
+        } catch (Exception e) {
+            log.error("导入客户数据失败", e);
+            throw new RuntimeException("导入客户数据失败");
+        }
+    }
+
+    /**
+     * 组装数据列表
+     *
+     * @param allData
+     * @return
+     */
+    public List<AdminSysCustomerDataInsertOrUpdateDTO> getDTOList(List<LinkedHashMap<Integer, Object>> allData) {
+        // 查询学段数据
+        List<SysParamBaseDataEntity> sysParamBaseDataEntities = sysCustomerUserCommonService.queryParamBaseData(0);
+        if (CollUtil.isEmpty(sysParamBaseDataEntities)) {
+            throw new BusinessException("参数配置学段未设置,导入失败");
+        }
+        // 查询省份数据
+        List<DictProvinceRegionBO> dictProvinceRegionBOS = dictProvinceRegionService.listUsed();
+        if (CollUtil.isEmpty(dictProvinceRegionBOS)) {
+            throw new BusinessException("参数配置省份未设置,导入失败");
+        }
+
+        //查询城市数据
+        List<DictCityRegionBO> dictCityRegionBOS =
+                dictCityRegionService.queryCityByParentCodes(dictProvinceRegionBOS.stream().map(DictProvinceRegionBO::getCode).toList());
+        // 返回结束数据
+        List<AdminSysCustomerDataInsertOrUpdateDTO> dtoLists = Lists.newArrayList();
+        //获取标题行数据
+        LinkedHashMap<Integer, Object> titleRowData = allData.getFirst();
+        // 删除标题行数据
+        allData.remove(titleRowData);
+
+        for (LinkedHashMap<Integer, Object> rowData : allData) {
+            AdminSysCustomerDataInsertOrUpdateDTO dto = new AdminSysCustomerDataInsertOrUpdateDTO();
+            // 设置标题行数据到dto中
+            dto.setName((String) rowData.get(0));
+
+            if (rowData.get(1) == null) {
+                throw new BusinessException("学段不能为空");
+            }
+            dto.setStageName((String) rowData.get(1));
+            List<SysParamBaseDataEntity> stageList = sysParamBaseDataEntities.stream()
+                    .filter(sysParamBaseDataEntity -> sysParamBaseDataEntity.getTitle().equals(rowData.get(1)))
+                    .toList();
+            if (CollUtil.isEmpty(stageList)) {
+                throw new BusinessException(rowData.get(1)+"学段不存在,导入失败");
+            }
+            dto.setStageId(stageList.getFirst().getId());
+
+            if (rowData.get(2) == null) {
+                throw new BusinessException("省份不能为空");
+            }
+            dto.setProvinceName((String) rowData.get(2));
+            List<DictProvinceRegionBO> provinceList = dictProvinceRegionBOS.stream()
+                    .filter(dictProvinceRegionBO -> dictProvinceRegionBO.getName().equals(rowData.get(2)))
+                    .toList();
+            if (CollUtil.isEmpty(provinceList)) {
+                throw new BusinessException(rowData.get(2)+"省份不存在,导入失败");
+            }
+            dto.setProvinceId(provinceList.getFirst().getId());
+            if (rowData.get(3) == null) {
+                throw new BusinessException("城市不能为空");
+            }
+            dto.setCityName((String) rowData.get(3));
+            List<DictCityRegionBO> cityList = dictCityRegionBOS.stream()
+                    .filter(dictCityRegionBO -> dictCityRegionBO.getName().equals(rowData.get(3)))
+                    .toList();
+            if (CollUtil.isEmpty(cityList)) {
+                throw new BusinessException(rowData.get(3)+"城市不存在,导入失败");
+            }
+            dto.setCityId(cityList.getFirst().getId());
+
+            dto.setAddress((String) rowData.get(4));
+            dtoLists.add(dto);
+        }
+        return dtoLists;
+    }
 }

+ 19 - 6
src/main/java/com/jtzx/crm/module/sys/service/DictCityRegionService.java

@@ -3,6 +3,7 @@ package com.jtzx.crm.module.sys.service;
 import cc.uncarbon.framework.core.page.PageResult;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jtzx.crm.module.sys.entity.DictCityRegionEntity;
 import com.jtzx.crm.module.sys.mapper.DictCityRegionMapper;
@@ -26,7 +27,19 @@ public class DictCityRegionService {
 
     private final DictCityRegionMapper dictCityRegionMapper;
 
-
+    /**
+     * 根据父级代码查询城市列表
+     * @param parentCodes
+     * @return
+     */
+    public List<DictCityRegionBO> queryCityByParentCodes(List<String> parentCodes) {
+        return this.entityList2BOs(
+                dictCityRegionMapper.selectList(new LambdaQueryWrapper<DictCityRegionEntity>()
+                        .in(DictCityRegionEntity::getParentCode, parentCodes)
+                        .orderByAsc(DictCityRegionEntity::getParentCode)
+                )
+        );
+    }
 
 
     /*
@@ -68,7 +81,7 @@ public class DictCityRegionService {
         // 深拷贝
         List<DictCityRegionBO> ret = new ArrayList<>(entityList.size());
         entityList.forEach(
-            entity -> ret.add(this.entity2BO(entity))
+                entity -> ret.add(this.entity2BO(entity))
         );
 
         return ret;
@@ -82,10 +95,10 @@ public class DictCityRegionService {
      */
     private PageResult<DictCityRegionBO> entityPage2BOPage(Page<DictCityRegionEntity> entityPage) {
         return new PageResult<DictCityRegionBO>()
-            .setCurrent(entityPage.getCurrent())
-            .setSize(entityPage.getSize())
-            .setTotal(entityPage.getTotal())
-            .setRecords(this.entityList2BOs(entityPage.getRecords()));
+                .setCurrent(entityPage.getCurrent())
+                .setSize(entityPage.getSize())
+                .setTotal(entityPage.getTotal())
+                .setRecords(this.entityList2BOs(entityPage.getRecords()));
     }
 
 }

+ 5 - 16
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerFollowAuditService.java

@@ -98,22 +98,11 @@ public class SysCustomerFollowAuditService {
             throw new BusinessException(400, "客户数据不存在");
         }
         sysCustomerFollowAuditMapper.updateById(entity);
-        List<SysCustomerFollowAuditEntity> sysCustomerFollowAuditEntities =
-                sysCustomerFollowAuditMapper.selectList(
-                        new LambdaQueryWrapper<>(SysCustomerFollowAuditEntity.class)
-                                .select(
-                                        SysCustomerFollowAuditEntity::getId
-                                )
-                                .eq(SysCustomerFollowAuditEntity::getCustomerId, entity.getCustomerId())
-                );
-        if (CollUtil.isNotEmpty(sysCustomerFollowAuditEntities)) {
-            sysCustomerFollowAuditEntities.forEach(e -> {
-                e.setAuditStatus(auditStatus);
-                e.setAuditUserId(UserContextHolder.getUserId());
-                e.setAuditUserName(UserContextHolder.getUserName());
-                sysCustomerFollowAuditMapper.updateById(e);
-            });
-        }
+        sysCustomerFollowAuditMapper.delete(
+                new LambdaQueryWrapper<>(SysCustomerFollowAuditEntity.class)
+                        .eq(SysCustomerFollowAuditEntity::getCustomerId, entity.getCustomerId())
+                        .ne(SysCustomerFollowAuditEntity::getId, id)
+        );
         // 审核通过,设置客户数据表的赢单信息,以及赢单审核信息
         if (auditStatus == 1) {
             sysCustomerDataEntity.setSuccessStatus(1);

+ 20 - 1
src/main/java/com/jtzx/crm/module/sys/service/SysGroupService.java

@@ -4,9 +4,11 @@ import cc.uncarbon.framework.core.exception.BusinessException;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.jtzx.crm.module.sys.entity.SysCustomerFollowEntity;
 import com.jtzx.crm.module.sys.entity.SysGroupEntity;
 import com.jtzx.crm.module.sys.entity.SysUserGroupRelationEntity;
 import com.jtzx.crm.module.sys.entity.SysUserRoleRelationEntity;
+import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
 import com.jtzx.crm.module.sys.mapper.SysGroupMapper;
 import com.jtzx.crm.module.sys.mapper.SysUserGroupRelationMapper;
 import com.jtzx.crm.module.sys.mapper.SysUserRoleRelationMapper;
@@ -36,8 +38,11 @@ public class SysGroupService {
 
     private final SysUserRoleRelationMapper sysUserRoleRelationMapper;
 
+    private final SysCustomerFollowMapper sysCustomerFollowMapper;
+
     /**
      * 查询分组列表数据
+     *
      * @return
      */
     public List<SysGroupBO> queryGroupList() {
@@ -82,7 +87,21 @@ public class SysGroupService {
     @Transactional(rollbackFor = Exception.class)
     public void adminUpdate(AdminSysGroupInsertOrUpdateDTO dto) {
         log.info("[后台管理-后台分组数据-编辑] >> DTO={}", dto);
-        SysGroupEntity entity = new SysGroupEntity();
+        SysGroupEntity entity = sysGroupMapper.selectById(dto.getId());
+        if (!dto.getTitle().equals(entity.getTitle())) {
+            long count =
+                    sysCustomerFollowMapper.selectCount(
+                            new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                    .select(
+                                            SysCustomerFollowEntity::getId
+                                    )
+                                    .eq(SysCustomerFollowEntity::getClaimUserGroupId, dto.getId())
+                    );
+            if (count > 0) {
+                throw new BusinessException(400, "存在跟进数据,不能删除");
+            }
+        }
+
         BeanUtil.copyProperties(dto, entity);
 
         sysGroupMapper.updateById(entity);

+ 36 - 1
src/main/java/com/jtzx/crm/module/sys/service/SysParamBaseDataService.java

@@ -5,6 +5,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.jtzx.crm.module.sys.entity.SysParamBaseDataEntity;
+import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
 import com.jtzx.crm.module.sys.mapper.SysParamBaseDataMapper;
 import com.jtzx.crm.module.sys.model.request.AdminSysParamBaseDataInsertOrUpdateDTO;
 import com.jtzx.crm.module.sys.model.response.SysParamBaseDataBO;
@@ -28,6 +29,8 @@ public class SysParamBaseDataService {
 
     private final SysParamBaseDataMapper sysParamBaseDataMapper;
 
+    private final SysCustomerFollowMapper sysCustomerFollowMapper;
+
     /**
      * 查询学段
      *
@@ -131,8 +134,24 @@ public class SysParamBaseDataService {
     @Transactional(rollbackFor = Exception.class)
     public void update(AdminSysParamBaseDataInsertOrUpdateDTO dto) {
         log.info("[后台管理-学段,产品,职务,跟进管理-编辑] >> DTO={}", dto);
+        SysParamBaseDataEntity entity = sysParamBaseDataMapper.selectById(dto.getId());
+//        if (!entity.getTitle().equals(dto.getTitle())) {
+//            long count =
+//                    sysCustomerFollowMapper.selectCount(
+//                            new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+//                                    .select(
+//                                            SysCustomerFollowEntity::getId
+//                                    )
+//                                    .eq(dto.getType() == 0, SysCustomerFollowEntity::getStageId, dto.getId())
+//                                    .eq(dto.getType() == 1, SysCustomerFollowEntity::getProductId, dto.getId())
+//                                    .eq(dto.getType() == 2, SysCustomerFollowEntity::getPositionId, dto.getId())
+//                                    .eq(dto.getType() == 3, SysCustomerFollowEntity::getFollowId, dto.getId())
+//                    );
+//            if (count > 0) {
+//                throw new BusinessException(400, "存在跟进数据,不能删除");
+//            }
+//        }
         dto.setType(null);
-        SysParamBaseDataEntity entity = new SysParamBaseDataEntity();
         BeanUtil.copyProperties(dto, entity);
         sysParamBaseDataMapper.updateById(entity);
     }
@@ -149,6 +168,22 @@ public class SysParamBaseDataService {
             if (sysParamBaseDataEntity.getStatus() == 1) {
                 throw new BusinessException(400, "系统默认不能删除");
             }
+
+//            long count =
+//                    sysCustomerFollowMapper.selectCount(
+//                            new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+//                                    .select(
+//                                            SysCustomerFollowEntity::getId
+//                                    )
+//                                    .eq(sysParamBaseDataEntity.getType() == 0, SysCustomerFollowEntity::getStageId, sysParamBaseDataEntity.getId())
+//                                    .eq(sysParamBaseDataEntity.getType() == 1, SysCustomerFollowEntity::getProductId, sysParamBaseDataEntity.getId())
+//                                    .eq(sysParamBaseDataEntity.getType() == 2, SysCustomerFollowEntity::getPositionId, sysParamBaseDataEntity.getId())
+//                                    .eq(sysParamBaseDataEntity.getType() == 3, SysCustomerFollowEntity::getFollowId, sysParamBaseDataEntity.getId())
+//                    );
+//            if (count > 0) {
+//                throw new BusinessException(400, "存在跟进数据,不能删除");
+//            }
+
             List<SysParamBaseDataEntity> dataEntityList =
                     sysParamBaseDataMapper.selectList(
                             new LambdaQueryWrapper<>(sysParamBaseDataEntity)

+ 13 - 7
src/main/java/com/jtzx/crm/module/sys/service/SysUserGroupRelationService.java

@@ -49,8 +49,11 @@ public class SysUserGroupRelationService {
 
     private final AsyncVThreadConfiguration asyncVThreadConfiguration;
 
+    private final SysCustomerFollowMapper sysCustomerFollowMapper;
+
     /**
      * 查询所有用户(左侧列表数据)
+     *
      * @return
      */
     public List<SysUserListBO> queryAllSysUserList(String username) {
@@ -77,6 +80,7 @@ public class SysUserGroupRelationService {
 
     /**
      * 分页查询表格数据
+     *
      * @param dto
      * @return
      */
@@ -234,6 +238,7 @@ public class SysUserGroupRelationService {
 
     /**
      * 分组管理,查询表格数据(第一种表格形式的数据)
+     *
      * @return
      */
     public List<GroupUserProvinceBO> queryTableData() {
@@ -322,7 +327,7 @@ public class SysUserGroupRelationService {
                                 .sorted(Comparator.comparing(SysGroupEntity::getSortCode))
                                 .forEach(groupEntity -> {
                                     //设置默认
-                                    userData.put(groupEntity.getId(), "-");
+                                    userData.put(groupEntity.getId(), Lists.newArrayList());
                                     if (CollUtil.isNotEmpty(userGroupRelationEntityList)) {
                                         List<GroupUserBO> userBOS = Lists.newArrayList();
                                         userGroupRelationEntityList.stream()
@@ -389,7 +394,7 @@ public class SysUserGroupRelationService {
         userRoleRelationDTO.setUserId(dto.getUserId());
         userRoleRelationDTO.setRoleId(3L);
         userRoleRelationDTO.setGroupId(dto.getGroupId());
-        sysUserRoleRelationService.adminInsert(userRoleRelationDTO);
+        sysUserRoleRelationService.adminInsertGroupUser(userRoleRelationDTO);
         //异步执行更新用户角色问题
         asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
                 sysUserRoleRelationService.updateUserRole(dto.getUserId()));
@@ -405,16 +410,16 @@ public class SysUserGroupRelationService {
     public void adminDelete(Long id) {
         log.info("[后台管理-数据表注释-删除] >> id={}", id);
         SysUserGroupRelationEntity sysUserGroupRelationEntity = sysUserGroupRelationMapper.selectById(id);
+        sysUserGroupRelationMapper.deleteById(id);
         if (sysUserGroupRelationEntity != null) {
-            sysUserGroupRelationMapper.deleteById(id);
             //删除普通成员角色
             sysUserRoleRelationService.delete(sysUserGroupRelationEntity.getUserId(),
                     sysUserGroupRelationEntity.getGroupId(), "Member");
+            sysUserRoleRelationService.updateUserRole(sysUserGroupRelationEntity.getUserId());
             //异步执行更新用户角色问题
-            asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
-                    sysUserRoleRelationService.updateUserRole(sysUserGroupRelationEntity.getUserId()));
+//            asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
+//                    sysUserRoleRelationService.updateUserRole(sysUserGroupRelationEntity.getUserId()));
         }
-
     }
 
 
@@ -446,7 +451,8 @@ public class SysUserGroupRelationService {
                                 SysUserGroupRelationEntity::getCityId,
                                 SysUserGroupRelationEntity::getProvinceId,
                                 SysUserGroupRelationEntity::getGroupId,
-                                SysUserGroupRelationEntity::getUserId
+                                SysUserGroupRelationEntity::getUserId,
+                                SysUserGroupRelationEntity::getCreatedAt
                         )
                         .orderByAsc(SysUserGroupRelationEntity::getCreatedAt)
         );

+ 79 - 42
src/main/java/com/jtzx/crm/module/sys/service/SysUserRoleRelationService.java

@@ -52,43 +52,42 @@ public class SysUserRoleRelationService {
 
     /**
      * 更新用户redis中的角色信息
+     *
      * @param userId
      */
+    @Transactional(rollbackFor = Exception.class)
     public void updateUserRole(Long userId) {
 
-        try {
-            Thread.sleep(200); // 当前线程休眠 200 毫秒
-            List<String> roleValueLists = Lists.newArrayList();
-            List<Long> roleIdList = Lists.newArrayList();
-            List<SysUserRoleRelationEntity> roleRelationEntityList =
-                    sysUserRoleRelationMapper.selectList(
-                            new LambdaQueryWrapper<>(SysUserRoleRelationEntity.class)
-                                    .select(
-                                            SysUserRoleRelationEntity::getRoleValue,
-                                            SysUserRoleRelationEntity::getRoleId
-                                    )
-                                    .eq(SysUserRoleRelationEntity::getUserId, userId)
-                    );
-            if (CollUtil.isNotEmpty(roleRelationEntityList)) {
-                roleValueLists.addAll(
-                        roleRelationEntityList.stream()
-                                .map(SysUserRoleRelationEntity::getRoleValue)
-                                .toList());
-
-                roleIdList.addAll(
-                        roleRelationEntityList.stream()
-                                .map(SysUserRoleRelationEntity::getRoleId)
-                                .toList());
-            }
-            UserContextHolder.getUserContext().setRoles(roleValueLists.stream().distinct().toList());
-            UserContextHolder.getUserContext().setRolesIds(new HashSet<>(roleIdList));
-        } catch (InterruptedException e) {
-            log.error(e.getMessage());
+        List<String> roleValueLists = Lists.newArrayList();
+        List<Long> roleIdList = Lists.newArrayList();
+        List<SysUserRoleRelationEntity> roleRelationEntityList =
+                sysUserRoleRelationMapper.selectList(
+                        new LambdaQueryWrapper<>(SysUserRoleRelationEntity.class)
+                                .select(
+                                        SysUserRoleRelationEntity::getRoleValue,
+                                        SysUserRoleRelationEntity::getRoleId
+                                )
+                                .eq(SysUserRoleRelationEntity::getUserId, userId)
+                );
+        if (CollUtil.isNotEmpty(roleRelationEntityList)) {
+            roleValueLists.addAll(
+                    roleRelationEntityList.stream()
+                            .map(SysUserRoleRelationEntity::getRoleValue)
+                            .toList());
+
+            roleIdList.addAll(
+                    roleRelationEntityList.stream()
+                            .map(SysUserRoleRelationEntity::getRoleId)
+                            .toList());
         }
+        UserContextHolder.getUserContext().setRoles(roleValueLists.stream().distinct().toList());
+        UserContextHolder.getUserContext().setRolesIds(new HashSet<>(roleIdList));
+
     }
 
     /**
      * 查询角色下拉数据列表
+     *
      * @return
      */
     public List<SysRoleListBO> queryRoleData() {
@@ -110,6 +109,7 @@ public class SysUserRoleRelationService {
 
     /**
      * 分页查询表格数据列表
+     *
      * @param dto
      * @return
      */
@@ -299,6 +299,7 @@ public class SysUserRoleRelationService {
 
     /**
      * 处理数据
+     *
      * @param roleEntity
      * @param groupEntityList
      * @param roleRelationEntityList
@@ -359,6 +360,7 @@ public class SysUserRoleRelationService {
 
     /**
      * 处理用户数据
+     *
      * @param roleRelationEntityList
      * @param sysUserEntities
      * @return
@@ -412,32 +414,67 @@ public class SysUserRoleRelationService {
         SysUserRoleRelationEntity entity = new SysUserRoleRelationEntity()
                 .setUserId(dto.getUserId()).setRoleId(dto.getRoleId()).setGroupId(dto.getGroupId()).setRoleValue(sysRoleEntity.getValue());
         sysUserRoleRelationMapper.insert(entity);
-        if (sysRoleEntity.getValue().equals("Admin")) {
-            CrmAdminStpUtil.kickout(dto.getUserId());
-        } else {
-            //异步执行更新用户角色问题
-            asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
-                    this.updateUserRole(dto.getUserId()));
-        }
+        CrmAdminStpUtil.kickout(dto.getUserId());
+        this.updateUserRole(dto.getUserId());
+//        if (sysRoleEntity.getValue().equals("Admin")) {
+//            CrmAdminStpUtil.kickout(dto.getUserId());
+//        }
+//        else {
+//            //异步执行更新用户角色问题
+//            asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
+//                    this.updateUserRole(dto.getUserId()));
+//        }
         return entity.getId();
     }
 
 
+    @Transactional(rollbackFor = Exception.class)
+    public void adminInsertGroupUser(UserRoleRelationInsertDTO dto) {
+
+        long count =
+                sysUserRoleRelationMapper.selectCount(
+                        new LambdaQueryWrapper<>(SysUserRoleRelationEntity.class)
+                                .select(SysUserRoleRelationEntity::getUserId)
+                                .eq(SysUserRoleRelationEntity::getRoleId, dto.getRoleId())
+                                .eq(SysUserRoleRelationEntity::getUserId, dto.getUserId())
+                                .eq(dto.getGroupId() != null, SysUserRoleRelationEntity::getGroupId, dto.getGroupId())
+                );
+        if (count == 0) {
+            SysRoleEntity sysRoleEntity = sysRoleMapper.selectById(dto.getRoleId());
+            SysUserRoleRelationEntity entity = new SysUserRoleRelationEntity()
+                    .setUserId(dto.getUserId()).setRoleId(dto.getRoleId()).setGroupId(dto.getGroupId()).setRoleValue(sysRoleEntity.getValue());
+            sysUserRoleRelationMapper.insert(entity);
+            this.updateUserRole(dto.getUserId());
+//            if (sysRoleEntity.getValue().equals("Admin")) {
+//                CrmAdminStpUtil.kickout(dto.getUserId());
+//            } else {
+//                //异步执行更新用户角色问题
+//                asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
+//                        this.updateUserRole(dto.getUserId()));
+//            }
+        }
+
+    }
+
+    @Transactional(rollbackFor = Exception.class)
     public void delete(Long id) {
         SysUserRoleRelationEntity roleRelationEntity = sysUserRoleRelationMapper.selectById(id);
         if (roleRelationEntity != null) {
             sysUserRoleRelationMapper.deleteById(id);
             //如果处理的是管理员,需要重新登陆
-            if (roleRelationEntity.getRoleValue().equals("Admin")) {
-                CrmAdminStpUtil.kickout(roleRelationEntity.getUserId());
-            } else {
-                //异步执行更新用户角色问题
-                asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
-                        this.updateUserRole(roleRelationEntity.getUserId()));
-            }
+            CrmAdminStpUtil.kickout(roleRelationEntity.getUserId());
+//            this.updateUserRole(roleRelationEntity.getUserId());
+//            if (roleRelationEntity.getRoleValue().equals("Admin")) {
+//                CrmAdminStpUtil.kickout(roleRelationEntity.getUserId());
+//            } else {
+//                //异步执行更新用户角色问题
+//                asyncVThreadConfiguration.getAsyncExecutor().execute(() ->
+//                        this.updateUserRole(roleRelationEntity.getUserId()));
+//            }
         }
     }
 
+    @Transactional(rollbackFor = Exception.class)
     public void delete(Long userId, Long groupId, String roleValue) {
         sysUserRoleRelationMapper.delete(
                 new LambdaQueryWrapper<>(SysUserRoleRelationEntity.class)

+ 17 - 5
src/main/java/com/jtzx/crm/module/sys/service/SysUserService.java

@@ -77,7 +77,7 @@ public class SysUserService {
     /**
      * 根据 ID 取详情
      *
-     * @param id               主键ID
+     * @param id 主键ID
      * @return null or BO
      */
     public SysUserBO getOneById(Long id) throws BusinessException {
@@ -118,8 +118,18 @@ public class SysUserService {
     @Transactional(rollbackFor = Exception.class)
     public void adminUpdate(InsertOrUpdateSysUserDTO dto) {
         log.info("[后台管理-编辑后台用户] >> 入参={}", dto);
+        SysUserEntity entity = sysUserMapper.selectById(dto.getId());
+        if (!entity.getUserName().equals(dto.getUsername())) {
+            long count =
+                    sysUserGroupRelationMapper.selectCount(
+                            new LambdaQueryWrapper<>(SysUserGroupRelationEntity.class)
+                                    .eq(SysUserGroupRelationEntity::getUserId, dto.getId())
+                    );
+            if (count > 0) {
+                throw new BusinessException(400, "不能编辑,请先删除分组管理中的人员配置");
+            }
+        }
         this.checkExistence(dto);
-        SysUserEntity entity = new SysUserEntity();
         BeanUtil.copyProperties(dto, entity);
         // 手动处理异名字段
         entity.setPin(dto.getAccount());
@@ -147,8 +157,8 @@ public class SysUserService {
                         new LambdaQueryWrapper<>(SysUserRoleRelationEntity.class)
                                 .in(SysUserRoleRelationEntity::getUserId, ids)
                 );
-        if(size > 0){
-            throw new BusinessException(400,"不能删除,请先删除权限管理中的人员配置");
+        if (size > 0) {
+            throw new BusinessException(400, "不能删除,请先删除权限管理中的人员配置");
         }
         sysUserMapper.deleteByIds(ids);
     }
@@ -232,6 +242,7 @@ public class SysUserService {
 
     /**
      * 启用或禁用用户状态
+     *
      * @param userId
      */
     public Integer updateUserStatus(Long userId) {
@@ -251,6 +262,7 @@ public class SysUserService {
 
     /**
      * 启用或禁用用户跟进状态
+     *
      * @param userId
      * @param followType 开关的跟进类型,公海跟进-publicFollow,历史跟进 -historyFollow
      */
@@ -298,7 +310,7 @@ public class SysUserService {
     /**
      * 实体转 BO
      *
-     * @param entity       实体
+     * @param entity 实体
      * @return BO
      */
     private SysUserBO entity2BO(SysUserEntity entity) {

+ 4 - 4
src/main/resources/logback-spring.xml

@@ -2,11 +2,11 @@
 
 <configuration debug="false">
     <!-- 配置-彩色日志渲染类 -->
-    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
+    <conversionRule conversionWord="clr" class="org.springframework.boot.logging.logback.ColorConverter"/>
     <conversionRule conversionWord="wex"
-            converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
+                    class="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
     <conversionRule conversionWord="wEx"
-            converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
+                    class="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
 
     <!-- 常量-项目名称 -->
     <property name="APP_NAME" value="jtzx-crm"/>
@@ -185,7 +185,7 @@
         <includeCallerData>true</includeCallerData>
     </appender>
 
-    <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
+    <shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
 
     <logger name="io.undertow" level="WARN"/>
     <logger name="com.alibaba.nacos.client" level="ERROR"/>