Browse Source

Merge remote-tracking branch 'origin/dev' into dev

LT32820A 5 days ago
parent
commit
e1c7db4ead

+ 8 - 3
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java

@@ -27,6 +27,7 @@ import org.jeecg.modules.system.model.SysDepartTreeModel;
 import org.jeecg.modules.system.service.ISysDepartService;
 import org.jeecg.modules.system.service.ISysUserDepartService;
 import org.jeecg.modules.system.service.ISysUserService;
+import org.jeecg.modules.system.util.ExcelImportHandleUtil;
 import org.jeecg.modules.system.vo.SysDepartExportVo;
 import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
 import org.jeecgframework.poi.excel.ExcelImportUtil;
@@ -45,6 +46,7 @@ import org.springframework.web.servlet.ModelAndView;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -419,7 +421,8 @@ public class SysDepartController {
 			params.setHeadRows(1);
 			params.setNeedSave(true);
 			try {
-				listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), SysDepartExportVo.class, params);
+				InputStream inputStream = ExcelImportHandleUtil.fileStreamProcessing(file, 3, 0);
+				listSysDeparts = ExcelImportUtil.importExcel(inputStream, SysDepartExportVo.class, params);
 				sysDepartService.initializationImportSysDepart(listSysDeparts, errorMessageList);
 				return ImportExcelUtil.imporReturnRes(errorMessageList.size(), listSysDeparts.size() - errorMessageList.size(), errorMessageList);
 			} catch (Exception e) {
@@ -504,7 +507,8 @@ public class SysDepartController {
 				//update-end---author:wangshuai---date:2023-10-20---for: 注释掉原来的导入部门的逻辑---
 				
 				//update-begin---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
-				listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), SysDepartExportVo.class, params);
+				InputStream inputStream = ExcelImportHandleUtil.fileStreamProcessing(file, 3, 0);
+				listSysDeparts = ExcelImportUtil.importExcel(inputStream, SysDepartExportVo.class, params);
 				sysDepartService.importSysDepart(listSysDeparts,errorMessageList);
 				//update-end---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
 				
@@ -700,7 +704,8 @@ public class SysDepartController {
 			params.setHeadRows(1);
 			params.setNeedSave(true);
 			try {
-				listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), ExportDepartVo.class, params);
+				InputStream inputStream = ExcelImportHandleUtil.fileStreamProcessing(file, 3, 0);
+				listSysDeparts = ExcelImportUtil.importExcel(inputStream, ExportDepartVo.class, params);
 				sysDepartService.importExcel(listSysDeparts,errorMessageList);
 				//清空部门缓存
 				Set keys3 = redisTemplate.keys(CacheConstant.SYS_DEPARTS_CACHE + "*");

+ 5 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleController.java

@@ -478,6 +478,11 @@ public class SysRoleController {
 		// Step.1 组装查询条件
 //		QueryWrapper<SysRole> queryWrapper = QueryGenerator.initQueryWrapper(sysRole, request.getParameterMap());
 		String ids = request.getParameter("ids");
+		if (ids.length() > 2) {
+			ids = ids.substring(1, ids.length() - 1);
+		} else {
+			ids = null;
+		}
 		//Step.2 AutoPoi 导出Excel
 		ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
 		List<SysRole> pageList = sysRoleService.listExport(sysRole,ids);

+ 60 - 5
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java

@@ -16,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.catalina.User;
 import org.apache.commons.lang.StringUtils;
 import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.apache.shiro.authz.annotation.RequiresRoles;
@@ -34,8 +35,10 @@ import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
 import org.jeecg.modules.base.service.BaseCommonService;
 import org.jeecg.modules.system.entity.*;
 import org.jeecg.modules.system.model.DepartIdModel;
+import org.jeecg.modules.system.model.SysDepartTreeModel;
 import org.jeecg.modules.system.model.SysUserSysDepartModel;
 import org.jeecg.modules.system.service.*;
+import org.jeecg.modules.system.util.ExcelImportHandleUtil;
 import org.jeecg.modules.system.vo.SysDepartUsersVO;
 import org.jeecg.modules.system.vo.SysUserRoleVO;
 import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
@@ -45,6 +48,7 @@ import org.jeecgframework.poi.excel.def.NormalExcelConstants;
 import org.jeecgframework.poi.excel.entity.ExportParams;
 import org.jeecgframework.poi.excel.entity.ImportParams;
 import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.jeecgframework.poi.util.PoiPublicUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
@@ -54,7 +58,7 @@ import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
+import java.io.*;
 import java.net.URLDecoder;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -110,7 +114,8 @@ public class SysUserController {
 
     @Autowired
     private JeecgRedisClient jeecgRedisClient;
-    
+    private StringBuilder deptStr;
+
     /**
      * 获取租户下用户数据(支持租户隔离)
      * @param user
@@ -621,15 +626,22 @@ public class SysUserController {
                 String[] expectedHeaders = {"登录账号", "真实姓名", "性别", "电话", "工号", "所属部门"};
                 boolean isHeaderValid = checkHeader(headerRow, expectedHeaders);
 
+                InputStream inputStream = ExcelImportHandleUtil.fileStreamProcessing(file, 3, 0);
+
+
+                List<SysUser> listSysUsers = ExcelImportUtil.importExcel(inputStream, SysUser.class, params);
 
-                List<SysUser> listSysUsers = ExcelImportUtil.importExcel(file.getInputStream(), SysUser.class, params);
                 if (!isHeaderValid) {
                     errorMessage.add("文件 " + fileName + " 格式不正确");
                     errorLines =listSysUsers.size();
                     throw new IllegalArgumentException("文件格式不正确");
                 }
                 for (int i = 0; i < listSysUsers.size(); i++) {
+
                     SysUser sysUserExcel = listSysUsers.get(i);
+                    String depart = sysUserExcel.getDepartmentId();
+
+
                     if (StringUtils.isBlank(sysUserExcel.getPassword())) {
                         // 密码默认为 “123456”
                         sysUserExcel.setPassword("123456");
@@ -644,6 +656,15 @@ public class SysUserController {
                     String passwordEncode = PasswordUtil.encrypt(sysUserExcel.getUsername(), sysUserExcel.getPassword(), salt);
                     sysUserExcel.setPassword(passwordEncode);
                     try {
+                        if (depart.contains("/")) {
+                            String[] departNames = depart.split("/");
+                            List<SysDepartTreeModel> list = sysDepartService.queryMyDeptTreeList(null);
+                            SysDepartTreeModel nodeByPath = findNodeByPath(list, departNames);
+                            if (ObjectUtil.isEmpty(nodeByPath)) {
+                                throw new IllegalArgumentException("组织不存在");
+                            }
+                            sysUserExcel.setDepartmentId(nodeByPath.getId());
+                        }
 
                         if (ObjectUtil.isNull(sysUserExcel.getUsername()) || sysUserExcel.getUsername().isEmpty()) {
 //                            errorMessage.add("第 " + i+1 + " 行:用户名为空。");
@@ -676,7 +697,16 @@ public class SysUserController {
                         int lineNumber = i + 1;
                         // 通过索引名判断出错信息
                         if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_USERNAME)) {
-                            errorMessage.add("第 " + lineNumber + " 行:用户名已经存在,忽略导入。");
+                            String errMessage = "第 " + lineNumber + " 行:用户名已经存在,忽略导入。";
+                            List<SysUser> logicDeletedUserList = sysUserService.queryLogicDeleted();
+                            if (logicDeletedUserList.size() > 0) {
+                                List<String> usernames = logicDeletedUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
+                                //sysUserExcel的username是否在usernames中
+                                if (usernames.contains(sysUserExcel.getUsername())) {
+                                    errMessage = errMessage + "用户在回收站中存在。";
+                                }
+                            }
+                            errorMessage.add(errMessage);
                         } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_WORK_NO)) {
                             errorMessage.add("第 " + lineNumber + " 行:工号已经存在,忽略导入。");
                         } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_PHONE)) {
@@ -688,7 +718,9 @@ public class SysUserController {
                         } else if (message.contains("用户名为空")) {
                             errorMessage.add("第 " + lineNumber + " 行:用户名为空。");
                         } else if (message.contains("用户真实姓名为空")) {
-                            errorMessage.add("第 " + lineNumber + " 行:用户真实姓名为空。");
+                            errorMessage.add("第 " + lineNumber + " 行:用户真实姓名为空。用户名:" + sysUserExcel.getUsername());
+                        } else if (message.contains("组织不存在")) {
+                            errorMessage.add("第 " + lineNumber + " 行:组织不存在。用户名:" + sysUserExcel.getUsername());
                         } else {
                             errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
                             log.error(e.getMessage(), e);
@@ -2103,5 +2135,28 @@ public class SysUserController {
         return true;
     }
 
+// 递归查找指定路径对应的节点
+    public static SysDepartTreeModel findNodeByPath(List<SysDepartTreeModel> tree, String[] path) {
+        if (path == null || path.length == 0 || tree == null){
+            return null;
+        }
 
+        for (SysDepartTreeModel node : tree) {
+            if (node.getDepartName().equals(path[0])) {
+                if (path.length == 1) {
+                    // 找到了路径的最后一部分
+                    return node;
+                } else {
+                    String[] paths = Arrays.copyOfRange(path, 1, path.length);
+                    // 递归查找子节点
+                    SysDepartTreeModel result = findNodeByPath(node.getChildren(), paths);
+                    if (result != null) {
+                        return result;
+                    }
+                }
+            }
+        }
+        // 如果没有找到匹配的节点,返回null
+        return null;
+    }
 }

+ 1 - 1
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysRoleMapper.xml

@@ -58,7 +58,7 @@
         app_base_info sa ON r.app_id = sa.id
         WHERE 1=1
           <if test="ids!=null">
-            AND r.id in (#{ids})
+            AND r.id in (${ids})
         </if>
         <if test="role.appId!=null">
             AND r.app_id = #{role.appId}

+ 13 - 1
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDepartServiceImpl.java

@@ -1283,6 +1283,19 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
 		Map<String,SysDepart> departMap = new HashMap<>();
 		// orgCode编码长度
 		int codeLength = YouBianCodeUtil.ZHANWEI_LENGTH;
+
+		//对空数据进行删除
+		for (int i = 0; i < listSysDeparts.size(); i++) {
+			if (oConvertUtils.isEmpty(listSysDeparts.get(i).getDepartName()) &&
+				oConvertUtils.isEmpty(listSysDeparts.get(i).getDepartOrder()) &&
+				oConvertUtils.isEmpty(listSysDeparts.get(i).getDepartNameEn()) &&
+				oConvertUtils.isEmpty(listSysDeparts.get(i).getDescription()) &&
+				oConvertUtils.isEmpty(listSysDeparts.get(i).getMemo())) {
+				listSysDeparts.remove(i);
+				i--;
+			}
+		}
+
 		//循环第二遍导入数据
 		for (SysDepartExportVo departExportVo : listSysDeparts) {
 			SysDepart sysDepart = new SysDepart();
@@ -1394,7 +1407,6 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
 			item.setParentId(null);
 		});
 		importSysDepart(sysDepartExportVos, errorMessageList);
-		System.out.println(sysDepartExportVos);
 	}
 
 

+ 98 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/util/ExcelImportHandleUtil.java

@@ -0,0 +1,98 @@
+package org.jeecg.modules.system.util;
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ExcelImportHandleUtil {
+
+    /**
+     *
+     * @param file (上传的文件的对象)
+     * @param headerRowsNumber (表头有多少行)
+     * @param sheetIndex  (Sheet索引)
+     * @return inputStream (输入流)
+     * @throws IOException
+     */
+    public static InputStream fileStreamProcessing(MultipartFile file, int headerRowsNumber, int sheetIndex) throws IOException {
+        Workbook book = WorkbookFactory.create(file.getInputStream());
+        Sheet tempSheet = book.getSheetAt(sheetIndex);
+        int lastRowNum = tempSheet.getLastRowNum();
+
+        // 创建一个新的Workbook和Sheet
+        Workbook newBook = new XSSFWorkbook();
+        Sheet newSheet = newBook.createSheet("Filtered Data");
+
+        int newRowNum = 0; // 新Sheet的行号
+
+        // 复制前三行
+        for (int i = 0; i < headerRowsNumber; i++) {
+            Row row = tempSheet.getRow(i);
+            if (row != null) {
+                Row newRow = newSheet.createRow(newRowNum++);
+                for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
+                    Cell cell = row.getCell(j);
+                    if (cell != null) {
+                        Cell newCell = newRow.createCell(j);
+                        copyCell(cell, newCell);
+                    }
+                }
+            }
+        }
+
+        for (int i = headerRowsNumber; i <= lastRowNum; i++) {
+            Row row = tempSheet.getRow(i);
+            if (row != null) {
+                short firstCellNum = row.getFirstCellNum();
+                if (firstCellNum != -1) {
+                    // 复制行到新的Sheet
+                    Row newRow = newSheet.createRow(newRowNum++);
+                    for (int j = firstCellNum; j <= row.getLastCellNum(); j++) {
+                        Cell cell = row.getCell(j);
+                        if (cell != null) {
+                            Cell newCell = newRow.createCell(j);
+                            copyCell(cell, newCell);
+                        }
+                    }
+                }
+            }
+        }
+        // 将新的Workbook写入ByteArrayOutputStream
+        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
+        newBook.write(byteArrayOut);
+        newBook.close();
+        book.close();
+
+        // 获取InputStream
+        InputStream inputStream = new ByteArrayInputStream(byteArrayOut.toByteArray());
+        byteArrayOut.close();
+
+        return inputStream;
+    }
+
+    private static void copyCell(Cell oldCell, Cell newCell) {
+        switch (oldCell.getCellType()) {
+            case STRING:
+                newCell.setCellValue(oldCell.getStringCellValue());
+                break;
+            case NUMERIC:
+                newCell.setCellValue(oldCell.getNumericCellValue());
+                break;
+            case BOOLEAN:
+                newCell.setCellValue(oldCell.getBooleanCellValue());
+                break;
+            case FORMULA:
+                newCell.setCellFormula(oldCell.getCellFormula());
+                break;
+            default:
+                break;
+        }
+    }
+
+
+}

+ 20 - 6
jeecgboot-vue3/src/views/system/menu/components/AppPermissionTree.vue

@@ -263,6 +263,21 @@ function onTreeNodeSelect(key,{selectedNodes}) {
   toggleExpandAll(true);
 }
 
+function findAncestors(tree, targetId, path = []) {
+    for (let node of tree) {
+        if (node.key === targetId) {
+            return path;  
+        }
+        if (node.children) {
+            const result = findAncestors(node.children, targetId, [...path, node]);
+            if (result) {
+                return result;
+            }
+        }
+    }
+    return null;
+}
+
 function getNodeAllKey(node: any, children: any, key: string) {
   const result: any = [];
   result.push(node[key]);
@@ -289,15 +304,14 @@ function removeMatchingItems(arr1, arr2) {
 
 // tree勾选复选框事件
 function onCheck(o, e) {
-  // if (!Array.isArray(event)) {
-  //   checkedKeys.value = event.checked;
-  // } else {
-  //   checkedKeys.value = event;
-  // }
+  //勾选子节点时自动选择父节点与祖宗节点
+  const ancestors = findAncestors(treeData.value, e.node.key);
+  const ancestorsKeys = ancestors.map(item => item.key);
+  // console.log('ancestors', ancestors);
   const keys = getNodeAllKey(e.node, 'children', 'key');
   if (e.checked) {
     // 反复操作下可能会有重复的keys,得用new Set去重下
-    checkedKeys.value = [...new Set([...checkedKeys.value, ...keys])];
+    checkedKeys.value = [...new Set([...checkedKeys.value, ...keys,...ancestorsKeys])];
   } else {
     const result = removeMatchingItems(checkedKeys.value, keys);
     checkedKeys.value = result;

+ 1 - 1
jeecgboot-vue3/src/views/system/role/index.vue

@@ -114,7 +114,7 @@ const { prefixCls, tableContext, onImportXls, onExportXls } = useListPage({
   exportConfig: {
     name: '角色列表',
     url: ()=>{
-      const ids = encodeURIComponent(JSON.stringify(selectedRowKeys))
+      const ids = encodeURIComponent(JSON.stringify(selectedRowKeys.value))
       return `${getExportUrl}?ids=${ids}`;
     },
   },