48 Commits c1418a1570 ... e3bf435e53

Author SHA1 Message Date
  ZL e3bf435e53 Merge branch 'dev' into ZL 1 week ago
  LT32820A cddd3fb34a 解决缺陷 13694 补充修改 1 week ago
  LT32820A b915ee11e6 解决缺陷 13694 1 week ago
  LT32820A 2dafbed7e4 增加应用名称唯一性校验规则 1 week ago
  LT32820A e6314b52e6 Merge remote-tracking branch 'origin/dev' into dev 1 week ago
  LT32820A aa975febe2 增加实时检查应用名称是否已存在规则 后端 1 week ago
  LT32820A 865ccfd107 Merge remote-tracking branch 'origin/dev' into dev 1 week ago
  LT32820A a06185ba68 业务对接人控件显示id,不显示值问题 1 week ago
  LT32820A b2de8ae4e3 更改基础信息反审核标志位 1 week ago
  LT32820A 559ad4206b 更新 'jeecgboot-vue3/src/views/appmanage/addForm/Step4.vue' 1 week ago
  LT32820A 3a07112cd7 修改部分样式 1 week ago
  LT32820A e9a5534e9a 更新 'jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/AppmanageServiceImpl.java' 1 week ago
  LT32820A 4f9ad3a95e 解决完整应用注册后不显示一级菜单,以及一级菜单授权问题:由授权应用默认角色 改为=》授权应用相关人(管理员、开发、运维、业务) 1 week ago
  LT32820A 5411e5e6c6 Merge remote-tracking branch 'origin/dev' into dev 1 week ago
  LT32820A b16f5e1c6b 缺陷 13877 将应用注册流程结束=》执行WebApi 改为 执行业务单元并通过微服务调用,将存储用户id改为存储用户账号 1 week ago
  LT32820A 63fa7c9784 Merge remote-tracking branch 'origin/dev' into dev 1 week ago
  LT32820A 32ad22eb9e 解决 缺陷13697 1 week ago
  danch 6e44ae9eaf 数据字典-导入数据时,提示未导入成功,但实际已导入成功问题 1 week ago
  danch 2305a21546 Merge remote-tracking branch 'origin/dev' into dev 1 week ago
  danch 29d1b0ea38 数据字典-删除数据后,已选中记录未更新问题 1 week ago
  LT32820A 470fab6891 解决 缺陷13730 流程模块下线,系统无法登入 1 week ago
  GDW 276c4a48dc BUG修复:用户导入未校验用户名与用户真是姓名是否为空 1 week ago
  GDW 8d9b67b8ec Merge branch 'GDW-FIX' into dev 2 weeks ago
  GDW 3e5d5c97f7 BUG修复:#13561 部门、用户管理-导出按钮,不能导出勾选的某条信息问题 2 weeks ago
  ZL edf2b098fa Merge branch 'ZL' into dev 2 weeks ago
  GDW a141c0ec61 优化:组织树优化 2 weeks ago
  GDW c5597501bb Merge remote-tracking branch 'origin/dev' into dev 2 weeks ago
  GDW 9ed3225930 修复:初始化导入失败后返回错误文件 2 weeks ago
  danch 9e942dd20a Merge remote-tracking branch 'origin/dev' into dev 2 weeks ago
  danch eddde3a182 用户管理-查询方案删除,未同步删除查询方案内容问题 2 weeks ago
  GDW ce68dcd7f9 地址修改 2 weeks ago
  GDW 477f24987e BUG修复:#13561 部门、用户管理-导出按钮,不能导出勾选的某条信息问题 2 weeks ago
  GDW 000d244768 添加AutoLog注解 2 weeks ago
  GDW 5fd5dd3582 BUG修复:导入后复选框勾选错误 2 weeks ago
  GDW 339ea4c0ce Merge branch 'refs/heads/GDW-FIX' into dev 2 weeks ago
  GDW 856ec81e58 BUG修复:#13359 部门管理-搜索框关键字搜索BUG:取消关键字,默认勾选了子节点(二次提交) 2 weeks ago
  GDW 8a97ffca07 Merge remote-tracking branch 'origin/dev' into dev 2 weeks ago
  GDW 26e6f08c41 BUG修复:#13522 用户管理-点击右侧部门树,新增,部门没有默认选择选中的部门 2 weeks ago
  danch e06c52d8f1 1. 用户管理-新增查询方案,不刷新页面不显示问题 2 weeks ago
  GDW 0a15dfe3af BUG修复:##13501 用户管理-编辑页面删除性别字段值,提示“修改成功”后,详情页依旧显示改字段值问题 2 weeks ago
  GDW cf65593ae1 BUG修复:#13423 用户管理-BUG:回收站删除操作,已选中记录未更新问题(同用户列表删除问题) 3 weeks ago
  GDW 0efdf3c401 BUG修复:#13421 用户管理-BUG:用户信息列表删除时,已选中记录数量未变更问题 3 weeks ago
  GDW 7e19fa96cd BUG修复:#13420 用户管理-取消关键字搜索,不点击搜索按钮,自动刷新页面显示全部部门信息(优化建议) 3 weeks ago
  GDW a065eba32e BUG修复:#13375 用户管理-页面展示,每次切换用户信息表格页面,空格大小都不同 3 weeks ago
  GDW fe1e4019d5 BUG修复:#13359 部门管理-搜索框关键字搜索BUG:取消关键字,默认勾选了子节点 3 weeks ago
  GDW 2ce3d0327b BUG修复:#13346 部门管理-取消关键字时,是否可以直接刷新页面(优化建议) 3 weeks ago
  GDW cf7bf8e07e BUG修复:#13371 部门管理-删除部门时,已选中记录未更新,且再次选中子节点时累加问题 3 weeks ago
  GDW 554b4cb991 BUG修复:BUG#13371 取消父节点勾选,所有子节点未取消勾选问题及已选中数量记录问题问题修复 3 weeks ago
44 changed files with 763 additions and 377 deletions
  1. 24 15
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/AppmanageController.java
  2. 17 1
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java
  3. 2 2
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java
  4. 49 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java
  5. 1 1
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/AppmanageEntity/APP_Register_workFlow_FormEntity.java
  6. 4 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysUserPermission.java
  7. 1 5
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/AppBaseInfoMapper.java
  8. 21 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/AppCustomMapper.java
  9. 5 5
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/AppBaseInfoMapper.xml
  10. 4 4
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/AppmanageService.java
  11. 98 89
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/AppmanageServiceImpl.java
  12. 78 8
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/util/AppManageUtil.java
  13. 0 1
      jeecg-boot/jeecg-server-cloud/jflow-cloud-start/src/main/java/org/jeecg/JeecgJflowCloudApplication.java
  14. 3 3
      jeecg-boot/jflow-core/src/main/java/bp/difference/client/SystemClient.java
  15. 26 0
      jeecg-boot/jflow-core/src/main/java/bp/sys/BuessUnitAfterAppCheckPass.java
  16. 20 1
      jeecg-boot/jflow-core/src/main/java/bp/sys/base/Glo.java
  17. 11 12
      jeecg-boot/jflow-core/src/main/java/bp/wf/WorkNode.java
  18. 1 9
      jeecg-boot/jflow-core/src/main/java/bp/wf/httphandler/WF_Comm.java
  19. 1 1
      jeecgboot-vue3/.env.production
  20. 1 1
      jeecgboot-vue3/jflow-vue-core/assets/GPN_Emp-57dc0d67.js
  21. 1 1
      jeecgboot-vue3/jflow-vue-core/assets/GPN_Emp-c3891a55.js
  22. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_Dept2Emp-1adb0fbf.js
  23. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_Dept2Emp-f31e8155.js
  24. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FlowSort2Flow-211db7d6.js
  25. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FlowSort2Flow-f61eb57f.js
  26. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FrmSort2Frm-1d2f3bc0.js
  27. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FrmSort2Frm-98f3d82c.js
  28. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_TemplateSort2Template-63b1f209.js
  29. 0 0
      jeecgboot-vue3/jflow-vue-core/assets/TreeEns_TemplateSort2Template-b5f22e48.js
  30. 1 1
      jeecgboot-vue3/src/api/sys/user.ts
  31. 45 19
      jeecgboot-vue3/src/components/Lttc/BaseService/LTTCBaseServiceAdvancedSearch.vue
  32. 5 7
      jeecgboot-vue3/src/store/modules/user.ts
  33. 4 1
      jeecgboot-vue3/src/views/appmanage/AppBaseInfo.api.ts
  34. 6 8
      jeecgboot-vue3/src/views/appmanage/AppInfoList.vue
  35. 3 4
      jeecgboot-vue3/src/views/appmanage/addForm/Step1.vue
  36. 17 11
      jeecgboot-vue3/src/views/appmanage/addForm/Step4.vue
  37. 14 3
      jeecgboot-vue3/src/views/appmanage/addForm/data.tsx
  38. 70 8
      jeecgboot-vue3/src/views/system/depart/components/DepartLeftTree.vue
  39. 2 2
      jeecgboot-vue3/src/views/system/depart/index.vue
  40. 183 149
      jeecgboot-vue3/src/views/system/dict/index.vue
  41. 9 0
      jeecgboot-vue3/src/views/system/user/UserDrawer.vue
  42. 14 0
      jeecgboot-vue3/src/views/system/user/UserRecycleBinModal.vue
  43. 16 4
      jeecgboot-vue3/src/views/system/user/index.vue
  44. 6 1
      jeecgboot-vue3/src/views/system/user/user.data.ts

+ 24 - 15
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/AppmanageController.java

@@ -1,5 +1,8 @@
 package org.jeecg.modules.system.controller;
 
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -11,10 +14,9 @@ import org.jeecg.modules.system.entity.AppmanageEntity.*;
 import org.jeecg.modules.system.service.AppmanageService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import springfox.documentation.spring.web.json.Json;
+
+import java.util.*;
 
 /**
  * 功能描述
@@ -44,7 +46,6 @@ public class AppmanageController {
     @ApiOperation("删除应用信息")
     @PostMapping("/delete")
     public Result<Boolean> deleteAppInfo(@RequestBody String[] infos){
-        System.out.println("来到删除信息:"+ Arrays.toString(infos));
         return Result.ok(appInfoService.deleteAppInfo(infos));
     }
 
@@ -152,12 +153,6 @@ public class AppmanageController {
     }
 
 
-    // 判断当前登录用户是否为信息部用户
-    @GetMapping("/isInfoUser")
-    public Result<Boolean> isInfoUser(){
-        return Result.ok(appInfoService.isInfoUser());
-    }
-
     // 是否拥有平台应用管理员角色
     @GetMapping("/isAppAdmin")
     public Result<Boolean> isAppAdmin(){
@@ -184,10 +179,24 @@ public class AppmanageController {
     }
 
     // 应用注册审核通过后续处理(微服务调用)
-    @GetMapping("/afterAppCheckPass")
-    public <T> void afterAppCheckPass(@RequestParam("appid")String appid, @RequestParam("formData") T formData){
-        System.out.println("应用注册审核通过后续处理:"+formData);
-        appInfoService.afterAppCheckPass(appid, formData);
+    @PostMapping("/afterAppCheckPass")
+    public void afterAppCheckPass(@RequestBody Long id) {
+        System.out.println("应用注册审核通过后续处理:"+id);
+        try {
+            appInfoService.afterAppCheckPass(id);
+        }catch (Exception e){
+            System.out.println("应用注册审核通过后续处理错误:"+e);
+
+        }
+    }
+
+    @GetMapping("/appNameIsExist")
+    public Result<String> AppNameIsExist(String appName){
+        boolean b = appInfoService.AppNameIsExist(appName);
+        if (b){
+            return Result.error("应用名称已存在");
+        }
+        return Result.ok("检查通过");
     }
 
     // 应用注册流程被撤销 后续处理(微服务调用)

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

@@ -8,6 +8,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.config.TenantContext;
 import org.jeecg.common.constant.CacheConstant;
 import org.jeecg.common.constant.CommonConstant;
@@ -18,6 +19,7 @@ import org.jeecg.common.util.ImportExcelUtil;
 import org.jeecg.common.util.YouBianCodeUtil;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
+import org.jeecg.modules.base.service.BaseCommonService;
 import org.jeecg.modules.system.entity.SysDepart;
 import org.jeecg.modules.system.entity.SysUser;
 import org.jeecg.modules.system.model.DepartIdModel;
@@ -44,6 +46,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -65,6 +68,8 @@ public class SysDepartController {
 	private ISysUserService sysUserService;
 	@Autowired
 	private ISysUserDepartService sysUserDepartService;
+	@Autowired
+	private BaseCommonService baseCommonService  ;
 	/**
 	 * 查询数据 查出我的部门,并以树结构数据格式响应给前端
 	 *
@@ -382,12 +387,23 @@ public class SysDepartController {
 				"2、部门路径用英文字符/分割,部门名称为部门路径的最后一位;\n" +
 				"3、部门从一级名称开始创建,如果有同级就需要多添加一行,如研发部/研发一部;研发部/研发二部;\n" +
 				"4、自定义的部门编码需要满足规则才能导入。如一级部门编码为A01,那么子部门为A01A01,同级子部门为A01A02,编码固定为三位,首字母为A-Z,后两位为数字0-99,依次递增;", "导出人:"+user.getRealname(), "导出信息"));
+		//去除未选中的
+		String selections = request.getParameter("selections");
+		if (oConvertUtils.isNotEmpty(selections)) {
+			List<String> selectionList = Arrays.asList(selections.split(","));
+			List<SysDepartExportVo> filteredSysDepartExportVos = sysDepartExportVos.stream()
+					.filter(vo -> selectionList.contains(vo.getId()))
+					.collect(Collectors.toList());
+			mv.addObject(NormalExcelConstants.DATA_LIST, filteredSysDepartExportVos);
+			return mv;
+		}
         mv.addObject(NormalExcelConstants.DATA_LIST, sysDepartExportVos);
 		//update-end---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
         
 		return mv;
     }
 
+	@AutoLog
 	@RequestMapping(value = "/initializationImportExcel", method = RequestMethod.POST)
 	public Result<?> initializationImportExcel(HttpServletRequest request, HttpServletResponse response) {
 		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
@@ -405,11 +421,11 @@ public class SysDepartController {
 			try {
 				listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), SysDepartExportVo.class, params);
 				sysDepartService.initializationImportSysDepart(listSysDeparts, errorMessageList);
+				return ImportExcelUtil.imporReturnRes(errorMessageList.size(), listSysDeparts.size() - errorMessageList.size(), errorMessageList);
 			} catch (Exception e) {
 				throw new RuntimeException(e);
 			}
 		}
-
 		return Result.ok();
 	}
 

+ 2 - 2
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java

@@ -585,9 +585,9 @@ public class SysDictController {
 							successLines++;
                         //update-begin---author:wangshuai ---date:20220211  for:[JTC-1168]如果字典项值为空,则字典项忽略导入------------
 						}else if(integer == -1){
-                            errorLines++;
+							successLines++;
                             errorMessage.add("字典名称:" + po.getDictName() + ",对应字典列表的字典项值不能为空,忽略导入。");
-                        }else{
+                        } else{
                         //update-end---author:wangshuai ---date:20220211  for:[JTC-1168]如果字典项值为空,则字典项忽略导入------------
 							errorLines++;
 							int lineNumber = i + 1;

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

@@ -1,6 +1,7 @@
 package org.jeecg.modules.system.controller;
 
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
@@ -14,6 +15,7 @@ import io.swagger.models.auth.In;
 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.shiro.SecurityUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.apache.shiro.authz.annotation.RequiresRoles;
@@ -604,12 +606,28 @@ public class SysUserController {
         int successLines = 0, errorLines = 0, deptErrorLines = 0;
         for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
             MultipartFile file = entity.getValue();// 获取上传文件对象
+            String fileName = file.getOriginalFilename();
             ImportParams params = new ImportParams();
             params.setTitleRows(2);
             params.setHeadRows(1);
             params.setNeedSave(true);
             try {
+                // 读取表头
+                Workbook workbook = WorkbookFactory.create(file.getInputStream());
+                Sheet sheet = workbook.getSheetAt(0);
+                Row headerRow = sheet.getRow(2);
+
+                // 预期的表头
+                String[] expectedHeaders = {"登录账号", "真实姓名", "性别", "电话", "工号", "所属部门"};
+                boolean isHeaderValid = checkHeader(headerRow, expectedHeaders);
+
+
                 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);
                     if (StringUtils.isBlank(sysUserExcel.getPassword())) {
@@ -626,6 +644,18 @@ public class SysUserController {
                     String passwordEncode = PasswordUtil.encrypt(sysUserExcel.getUsername(), sysUserExcel.getPassword(), salt);
                     sysUserExcel.setPassword(passwordEncode);
                     try {
+
+                        if (ObjectUtil.isNull(sysUserExcel.getUsername()) || sysUserExcel.getUsername().isEmpty()) {
+//                            errorMessage.add("第 " + i+1 + " 行:用户名为空。");
+//                            errorLines ++;
+                            throw new IllegalArgumentException("用户名为空");
+                        }
+                        if (ObjectUtil.isNull(sysUserExcel.getRealname()) || sysUserExcel.getRealname().isEmpty()) {
+//                            errorLines ++;
+//                            errorMessage.add("第 " + i+1 + " 行:用户真实姓名为空。");
+                            throw new IllegalArgumentException("用户真实姓名为空");
+                        }
+
                         sysUserService.save(sysUserExcel);
 
                         //设置所属部门
@@ -655,6 +685,10 @@ public class SysUserController {
                             errorMessage.add("第 " + lineNumber + " 行:电子邮件已经存在,忽略导入。");
                         }  else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER)) {
                             errorMessage.add("第 " + lineNumber + " 行:违反表唯一性约束。");
+                        } else if (message.contains("用户名为空")) {
+                            errorMessage.add("第 " + lineNumber + " 行:用户名为空。");
+                        } else if (message.contains("用户真实姓名为空")) {
+                            errorMessage.add("第 " + lineNumber + " 行:用户真实姓名为空。");
                         } else {
                             errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
                             log.error(e.getMessage(), e);
@@ -2054,5 +2088,20 @@ public class SysUserController {
 
     }
 
+    private boolean checkHeader(Row headerRow, String[] expectedHeaders) {
+        if (headerRow == null || headerRow.getLastCellNum() != expectedHeaders.length) {
+            return false;
+        }
+
+        for (int i = 0; i < expectedHeaders.length; i++) {
+            Cell cell = headerRow.getCell(i);
+            if (cell == null || !expectedHeaders[i].equals(cell.getStringCellValue())) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
 
 }

+ 1 - 1
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/AppmanageEntity/APP_Register_workFlow_FormEntity.java

@@ -32,7 +32,7 @@ public class APP_Register_workFlow_FormEntity {
     private String createBy;
     private String createTime;
     private String addType;
-    private int info_status;
+    private int infoStatus;
 
     // 文档信息部分
     private String requirement;

+ 4 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysUserPermission.java

@@ -63,4 +63,8 @@ public class SysUserPermission implements Serializable {
         this.userId = userId;
         this.permissionId = permissionId;
     }
+
+    public SysUserPermission() {
+
+    }
 }

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

@@ -50,11 +50,7 @@ public interface AppBaseInfoMapper extends BaseMapper<AppBaseInfo> {
             "check_user = #{baseInfo.checkUser}, " +
             "check_time = #{baseInfo.checkTime}, " +
             "check_tag = #{baseInfo.checkTag}, " +
-            "create_by = #{baseInfo.createBy}, " +
-            "create_time = #{baseInfo.createTime}, " +
-            "add_type = #{baseInfo.addType}, " +
-            "info_status = #{baseInfo.info_status}, " +
-            "del_flag = #{baseInfo.delFlag} " +
+            "info_Status = #{baseInfo.infoStatus}, " +
             "</set>" +
             "WHERE id = #{baseInfo.id}" +
             "</script>")

+ 21 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/AppCustomMapper.java

@@ -1,6 +1,7 @@
 package org.jeecg.modules.system.mapper;
 
 import org.apache.ibatis.annotations.*;
+import org.jeecg.modules.system.entity.AppmanageEntity.APP_Register_workFlow_FormEntity;
 import org.jeecg.modules.system.entity.AppmanageEntity.AppBaseInfo;
 import org.jeecg.modules.system.entity.AppmanageEntity.AppUserInfo;
 import org.jeecg.modules.system.entity.SysPermission;
@@ -25,6 +26,10 @@ public interface AppCustomMapper {
     @Select("SELECT username FROM sys_user WHERE id = #{userId}")
     String queryUsernameByUserId(@Param("userId") String userId);
 
+    // 通过用户账号查询用户id
+    @Select("SELECT id FROM sys_user WHERE username = #{username}")
+    String queryUserIdByUsername(@Param("username") String username);
+
     AppBaseInfo queryBaseInfoById(@Param("id") String id);
 
     List<AppUserInfo> queryAppUserByIdList(@Param("ids") List<String> ids);
@@ -84,4 +89,20 @@ public interface AppCustomMapper {
     @Update("UPDATE port_stationtype SET Name = #{appName} WHERE No = #{id}")
     void updateRoleToPortstationtype(@Param("id") String id, @Param("appName") String Name);
 
+    // 查询应用注册简易流程携带的表单数据
+    @Select("SELECT id, name, type, status, admin, developUser, operationUser, requirementUser, businessUser, menuInfo, descr, Register_type AS addType " +
+            "FROM app_base_info_flow WHERE OID = #{workid}")
+    AppBaseInfo queryEasyFlowFormData(@Param("workid") Long workid);
+
+    // 查询应用注册完整流程携带的表单数据
+    @Select("SELECT * FROM app_detail_info_workflow where OID = #{workid}")
+    APP_Register_workFlow_FormEntity queryFullFlowFormData(@Param("workid") Long workid);
+
+    // 检查应用名称是否在应用信息表或流程表里已经存在(多表查询 查询 app_base_info, app_base_info_flow, app_detail_info_workflow 里的name属性是否有符合的)
+    @Select({"SELECT 1 FROM app_base_info WHERE name = #{appName} and del_flag = 0 UNION",
+            "SELECT 1 FROM wf_empworks where workid = (SELECT OID FROM app_base_info_flow WHERE name = #{appName}) UNION",
+            "SELECT 1 FROM wf_empworks where workid = (SELECT OID FROM app_detail_info_workflow WHERE name = #{appName})"})
+    Integer checkAppNameIsExist(@Param("appName") String appName);
+
+
 }

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

@@ -6,11 +6,11 @@
         SELECT app.id, app.name, app.type, app.status, app.create_time, app.add_type, suserA.realname as admin, app.admin as adminid, suserA.phone as contact, suserB.realname as developUser,
         suserC.realname as businessUser, suserD.realname as requirementUser, suserE.realname as operationUser
         FROM app_base_info app
-        LEFT JOIN sys_user suserA ON app.admin = suserA.id
-        LEFT JOIN sys_user suserB ON app.develop_user = suserB.id
-        LEFT JOIN sys_user suserC ON app.business_user = suserC.id
-        LEFT JOIN sys_user suserD ON app.requirement_user = suserD.id
-        LEFT JOIN sys_user suserE ON app.operation_user = suserE.id
+        LEFT JOIN sys_user suserA ON app.admin = suserA.username
+        LEFT JOIN sys_user suserB ON app.develop_user = suserB.username
+        LEFT JOIN sys_user suserC ON app.business_user = suserC.username
+        LEFT JOIN sys_user suserD ON app.requirement_user = suserD.username
+        LEFT JOIN sys_user suserE ON app.operation_user = suserE.username
         WHERE 1=1 and app.del_flag = 0 and info_status != 0
         <if test="key != null and key != ''">
             AND app.name LIKE CONCAT('%', #{key}, '%')

+ 4 - 4
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/AppmanageService.java

@@ -54,9 +54,6 @@ public interface AppmanageService  {
     // 获取应用用户id集合
     List<String> getAppuserids(String appid);
 
-    // 是否为信息部用户
-    boolean isInfoUser();
-
     // 当前登录用户是否拥有平台应用管理员
     boolean isAppAdmin();
 
@@ -66,8 +63,11 @@ public interface AppmanageService  {
     // 是否为应用管理员或开发负责人、运维负责人
     boolean isAppAdminOrDevOrOpe(String appid);
 
-    <T> void afterAppCheckPass(String appid, T formData);
+    void afterAppCheckPass(Long id);
 
     void afterUnsendAppRegisterFlow(long workID);
+
+    // 查询应用名称是否已经存在流程里或者应用信息表里
+    Boolean AppNameIsExist(String appName);
 }
 

+ 98 - 89
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/AppmanageServiceImpl.java

@@ -3,6 +3,7 @@ package org.jeecg.modules.system.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import org.apache.shiro.SecurityUtils;
+import org.checkerframework.checker.units.qual.A;
 import org.jeecg.common.api.dto.message.TemplateMessageDTO;
 import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.system.query.QueryGenerator;
@@ -10,6 +11,7 @@ import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.common.util.RedisUtil;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.base.service.BaseCommonService;
+import org.jeecg.modules.jmreport.common.util.DateUtils;
 import org.jeecg.modules.system.controller.SysUserController;
 import org.jeecg.modules.system.entity.*;
 import org.jeecg.modules.system.entity.AppmanageEntity.*;
@@ -53,6 +55,10 @@ public class AppmanageServiceImpl implements AppmanageService {
     @Autowired
     private ISysRolePermissionService sysRolePermissionService;
 
+    // 给用户授权用
+    @Autowired
+    private ISysUserPermissionService sysUserPermissionService;
+
     // 添加菜单用
     @Autowired
     private ISysPermissionService sysPermissionService;
@@ -112,20 +118,9 @@ public class AppmanageServiceImpl implements AppmanageService {
         LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
         appBaseInfo.setCreateBy(loginUser.getId());
         appBaseInfo.setAddType(appInfo.getAddType());
-        appBaseInfo.setDelFlag(1);
+        appBaseInfo.setDelFlag(0);
         baseInfoMapper.insert(appBaseInfo);
 
-        // 提交至工作流的表单信息(将用户id换成用户账账号)
-        AppBaseInfo sendCheck_appBaseInfo = appBaseInfo;
-        sendCheck_appBaseInfo.setAdmin(customMapper.queryUsernameByUserId(appBaseInfo.getAdmin()));
-        if (appBaseInfo.getDevelopUser()!=null)
-            sendCheck_appBaseInfo.setDevelopUser(customMapper.queryUsernameByUserId(appBaseInfo.getDevelopUser()));
-        if (appBaseInfo.getOperationUser()!=null)
-            sendCheck_appBaseInfo.setOperationUser(customMapper.queryUsernameByUserId(appBaseInfo.getOperationUser()));
-        if (appBaseInfo.getRequirementUser()!=null)
-            sendCheck_appBaseInfo.setRequirementUser(customMapper.queryUsernameByUserId(appBaseInfo.getRequirementUser()));
-        if (appBaseInfo.getBusinessUser()!=null)
-            sendCheck_appBaseInfo.setBusinessUser(customMapper.queryUsernameByUserId(appBaseInfo.getBusinessUser()));
         AppDocInfo appDocInfo = appInfo.getAppDocInfoDTO();
         boolean hasEnvInfo = false;
         if (appInfo.getAppEnvInfoDTO()!=null) hasEnvInfo = appInfo.getAppEnvInfoDTO().size()>0;
@@ -133,7 +128,7 @@ public class AppmanageServiceImpl implements AppmanageService {
         String appid = appBaseInfo.getId();
         // 简易注册模式下添加基础信息即可
         if (appBaseInfo.getAddType().equals("easy")){
-             tag = appManageUtil.sendCheckWordFlow(sendCheck_appBaseInfo, "021", loginUser.getUsername(), "admin");
+             tag = appManageUtil.sendCheckWordFlow(appBaseInfo, "021", loginUser.getUsername(), "admin");
             // 发起流程失败则删除数据库内数据
             if (!tag){
                 customMapper.deleteAppBaseInfoNotLogic(appid);
@@ -143,7 +138,7 @@ public class AppmanageServiceImpl implements AppmanageService {
             APP_Register_workFlow_FormEntity appRegisterWorkFlowFormEntity = new APP_Register_workFlow_FormEntity();
             BeanUtils.copyProperties(appRegisterWorkFlowFormEntity, appDocInfo);
             // 基础信息最后一个复制,避免id为null
-            BeanUtils.copyProperties(appRegisterWorkFlowFormEntity, sendCheck_appBaseInfo);
+            BeanUtils.copyProperties(appRegisterWorkFlowFormEntity, appBaseInfo);
             if (hasEnvInfo){
                 AppManageUtil appManageUtil = new AppManageUtil();
                 appRegisterWorkFlowFormEntity = appManageUtil.TransitionEnvInfoToAppRegisterWorkFlowForm(appRegisterWorkFlowFormEntity, appInfo.getAppEnvInfoDTO());
@@ -191,14 +186,14 @@ public class AppmanageServiceImpl implements AppmanageService {
     @Transactional
     @Override
     public Boolean deleteAppInfo(String[] ids) {
-        // 需先判断用户是否拥有所删除的应用信息的权限(平台管理员-应用管理员)
+        // 需先判断用户是否拥有所删除的应用信息的权限(平台管理员-该应用的应用管理员)
         // 获取当前登录用户信息
         LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
 
-        // 查询当前应用的应用管理员信息
         for (String id : ids) {
             // 不能删除基础平台的应用信息
             if (id.equals("0")) return false;
+
             AppBaseInfo appBaseInfo = baseInfoMapper.selectById(id);
             if (!loginUser.getUsername().equals("admin")){
                 if (!(appBaseInfo.getAdmin().equals(loginUser.getId()))) return false;
@@ -248,7 +243,7 @@ public class AppmanageServiceImpl implements AppmanageService {
     @Override
     public Boolean editBaseInfo(AppBaseInfo baseInfo) {
         int i = baseInfoMapper.updateById(baseInfo);
-        customMapper.updateRoleToPortstationtype(baseInfo.getId(), baseInfo.getName());
+        if (baseInfo.getAddType().equals("full")) customMapper.updateRoleToPortstationtype(baseInfo.getId(), baseInfo.getName());
         // 保存成功解除反审核状态
         if (i>0) uncheckLock("AppbaseInfo"+baseInfo.getId());
         return i>0;
@@ -301,14 +296,10 @@ public class AppmanageServiceImpl implements AppmanageService {
     @Transactional
     public Boolean editUserInfo(AppUpdataUserInfo updataUserInfo) {
         String appid = updataUserInfo.getAppid();
-        // 移除应用用户时,将角色收回
+        // 移除应用用户时,将默认角色收回
         if (updataUserInfo.getDelUserids()!=null&&!updataUserInfo.getDelUserids().isEmpty()){
             updataUserInfo.getDelUserids().forEach(userid -> {
                 System.out.println("删除用户:"+userid);
-                // 获取要移除的用户的信息
-                QueryWrapper<AppUserInfo> userInfoPOQueryWrapper = new QueryWrapper<>();
-                userInfoPOQueryWrapper.eq("appid",appid).eq("userid",userid);
-                AppUserInfo userInfo = userInfoMapper.selectOne(userInfoPOQueryWrapper);
                 // 获取该用户在该应用下的角色信息
                 List<String> roleIds = sysUserRoleService.listByAppId(appid, userid);
                 // 删除该用户在该应用下的角色信息
@@ -357,7 +348,6 @@ public class AppmanageServiceImpl implements AppmanageService {
         return true;
     }
 
-
     /**
      * 组合条件查询应用基础信息
      * @param key 模糊查询关键字
@@ -411,7 +401,7 @@ public class AppmanageServiceImpl implements AppmanageService {
         // 获取当前登录用户
         LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
         // 当前登录用户与当前应用的基础信息的应用管理员id是否一致
-        appBaseInfo.setIsEdit(appBaseInfo.getAdmin().equals(loginUser.getId()));
+        appBaseInfo.setIsEdit(hasEditCurrentInfoPermission(id));
         return appBaseInfo;
     }
 
@@ -464,19 +454,6 @@ public class AppmanageServiceImpl implements AppmanageService {
                         queryParams.getFilteruserids(),
                         queryParams.getPageNo());
 
-                // 判断当前用户是否可进行编辑操作
-                LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
-                String managerId;
-                Map<String, String> appManagerUserInfo; // 应用管理员信息
-                // 先从 redis 查询应用管理员信息,如果为空,则查询数据库
-                appManagerUserInfo = (Map<String, String>) redisUtil.get("appManagerInfo");
-                if (appManagerUserInfo == null) {
-                    AppBaseInfo baseInfoPO = baseInfoMapper.selectById(queryParams.getAppid());
-                    managerId = baseInfoPO.getAdmin();
-                }else {
-                    managerId = appManagerUserInfo.get(queryParams.getAppid());
-                }
-                editUserInfoEntity.setIsEdit(loginUser.getId().equals(managerId));
                 AppBaseInfo appBaseInfo = baseInfoMapper.selectById(queryParams.getAppid());
                 // 查询用户角色信息
                 appUserInfos.forEach(map -> {
@@ -595,16 +572,6 @@ public class AppmanageServiceImpl implements AppmanageService {
         return null;
     }
 
-    // 是否为信息部用户
-    @Override
-    public boolean isInfoUser() {
-        String deptId = customMapper.queryDepartIdByDepartName("信息部");
-        // 获取当前登录用户id
-        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
-        String udeptId = customMapper.queryDepartIdByUserId(loginUser.getId());
-        return deptId.equals(udeptId);
-    }
-
     @Override
     public boolean isAppAdmin() {
         // 获取当前登录用户
@@ -639,10 +606,8 @@ public class AppmanageServiceImpl implements AppmanageService {
         LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
         // 如果是平台管理员
         if (loginUser.getUsername().equals("admin")) return true;
-        // 查询基础信息的应用管理员id,比较是否和当前登录用户一致
-        QueryWrapper<AppBaseInfo> baseInfoPOQueryWrapper = new QueryWrapper<>();
-        baseInfoPOQueryWrapper.select("admin").eq("id", appid);
-        AppBaseInfo baseInfo = baseInfoMapper.selectOne(baseInfoPOQueryWrapper);
+        // 查询应用管理员id,比较是否和当前登录用户一致
+        AppBaseInfo baseInfo = baseInfoMapper.selectById(appid);
         return loginUser.getId().equals(baseInfo.getAdmin());
     }
 
@@ -671,36 +636,31 @@ public class AppmanageServiceImpl implements AppmanageService {
 
 
     // 应用审核通过后续处理
-    public <T> void afterAppCheckPass(String appid, T formData) {
-
+    @Transactional
+    public void afterAppCheckPass(Long workid) {
+        String appid = null;
         try {
-            AppBaseInfo appBaseInfo = baseInfoMapper.queryAppBaseInfoById(appid);
-            appManageUtil.CompareOldAppBaseInfoAndNewAppBaseInfo(appBaseInfo, formData);
-            // 以通过审批的应用信息为准更新应用信息
-            int i = baseInfoMapper.updateBaseInfo(appBaseInfo);
-            String toUser = baseInfoMapper.queryUsernameById(appBaseInfo.getCreateBy());
-            //给申请注册应用信息的用户发送系统消息
-            TemplateMessageDTO message = new TemplateMessageDTO();
-            message.setAppId("0");
-            message.setToUser(toUser);
-            // 设置消息模板编码
-            message.setTemplateCode("app_examineAndapprove");
-            Map<String, String> templateParam = new HashMap<>();
-            templateParam.put("resultText","应用"+appBaseInfo.getName()+"注册审核通过");
-            message.setTemplateParam(templateParam);
-            sysBaseApi.sendTemplateAnnouncement(message);
-
-            // 该信息为完整注册时,通过审核后添加默认角色、菜单权限、菜单信息
-            if (appBaseInfo.getAddType().equals("full")){
+            AppBaseInfo baseInfoInFlow = customMapper.queryEasyFlowFormData(workid);
+            if (baseInfoInFlow == null){  // 完整注册需执行的操作
+                APP_Register_workFlow_FormEntity appRegisterWorkFlowForm = customMapper.queryFullFlowFormData(workid);
+                appid = appRegisterWorkFlowForm.getId();
+                baseInfoInFlow = appManageUtil.AppRegisterWorkFlowFormEntityToBaseInfo(appRegisterWorkFlowForm);
+                // 更新应用文档信息
+                AppDocInfo appDocInfo = appManageUtil.AppRegisterWorkFlowFormEntityToDocInfo(appRegisterWorkFlowForm);
+                editDocInfo(appDocInfo);
+                // 更新应用环境信息
+                AppEditEnvInfoEntity appEnvInfoList = appManageUtil.AppRegisterWorkFlowFormEntityToEnvInfo(appRegisterWorkFlowForm);
+                editEnvInfo(appEnvInfoList);
                 // 将通过完整注册的应用信息同步给JFlow的角色分类表
-                customMapper.addRoleToPortstationtype(appid, appBaseInfo.getName());
+                customMapper.addRoleToPortstationtype(appid, baseInfoInFlow.getName());
+
                 // 添加默认角色信息
                 SysRole role = new SysRole();
                 role.setAppId(appid);  // 设置角色所属应用信息
                 role.setRoleCode("default");  // 设置角色编码
-                role.setAppName(appBaseInfo.getName()) ;  // 设置角色的应用名称
-                role.setRoleName(appBaseInfo.getName()+"_默认用户角色");  // 设置角色名
-                role.setDescription(appBaseInfo.getName()+"默认角色");  // 设置备注
+                role.setAppName(baseInfoInFlow.getName()) ;  // 设置角色的应用名称
+                role.setRoleName(baseInfoInFlow.getName()+"_默认用户角色");  // 设置角色名
+                role.setDescription(baseInfoInFlow.getName()+"默认角色");  // 设置备注
                 sysRoleService.save(role);  // 添加角色
 
                 // 获取角色编码
@@ -710,39 +670,82 @@ public class AppmanageServiceImpl implements AppmanageService {
                 QueryWrapper<AppUserInfo> appUserInfoQueryWrapper = new QueryWrapper<>();
                 appUserInfoQueryWrapper.select("userid").eq("appid", appid);
                 List<AppUserInfo> appUserInfos = userInfoMapper.selectList(appUserInfoQueryWrapper);
-                List<String> useridlist = appUserInfos.stream().map(AppUserInfo::getUserid).collect(Collectors.toList());
-
-                // 应用默认角色分配给应用用户
-                SysUserRoleVO sysUserRoleVO = new SysUserRoleVO();
-                sysUserRoleVO.setRoleId(roleid);
-                sysUserRoleVO.setUserIdList(useridlist);
-                sysUserController.addSysUserRole(sysUserRoleVO);
+                if (!appUserInfos.isEmpty()){
+                    List<String> useridlist = appUserInfos.stream().map(AppUserInfo::getUserid).collect(Collectors.toList());
+                    // 应用默认角色分配给应用用户
+                    useridlist.forEach(userid -> {
+                        SysUserRole sysUserRole = new SysUserRole();
+                        sysUserRole.setRoleId(roleid);
+                        sysUserRole.setUserId(userid);
+                        sysUserRoleService.save(sysUserRole);
+                    });
+                }
 
                 // 创建该应用的一级菜单
-                SysPermission hassysPermission = customMapper.queryUrlByUrl(appBaseInfo.getMenuInfo());
+                SysPermission hassysPermission = customMapper.queryUrlByUrl(baseInfoInFlow.getMenuInfo());
                 if (hassysPermission == null){
                     SysPermission sysPermission = new SysPermission();
-                    sysPermission.setName(appBaseInfo.getName());
+                    sysPermission.setName(baseInfoInFlow.getName());
                     sysPermission.setAppId(appid);
-                    sysPermission.setUrl(appBaseInfo.getMenuInfo());
+                    sysPermission.setUrl(baseInfoInFlow.getMenuInfo());
                     // 设置组件(即 菜单路径去掉第一个 "/")
                     String component = sysPermission.getUrl().replaceFirst("^/", "");
                     sysPermission.setComponent(component);
                     sysPermission.setMenuType(0);
                     sysPermission.setRoute(true);
                     sysPermissionService.addPermission(sysPermission);
-                    // 授予应用默认角色访问一级菜单权限
-                    sysRolePermissionService.saveRolePermission(roleid, sysPermission.getId(),"");
+                    AfterCheckSaveUserPermission(baseInfoInFlow, sysPermission.getId());
+//                    sysRolePermissionService.saveRolePermission(roleid, sysPermission.getId());
                 }else {
-                    // 授予应用默认角色访问一级菜单权限
-                    sysRolePermissionService.saveRolePermission(roleid, hassysPermission.getId(),"");
+                    AfterCheckSaveUserPermission(baseInfoInFlow, hassysPermission.getId());
+//                    sysRolePermissionService.saveRolePermission(roleid, hassysPermission.getId());
                 }
+            }else {  // 简易注册需执行的操作
+                appid = baseInfoInFlow.getId();
             }
+            AfterCheckPublicOperation(appid,baseInfoInFlow);
         }catch (Exception e){
             System.out.println("应用审核通过后续处理错误:"+e);
+            baseCommonService.addLog("应用审核后续处理错误:"+workid+"__异常信息:"+e, CommonConstant.LOG_TYPE_4, 3 );
         }
     }
 
+    private void AfterCheckPublicOperation(String appid, AppBaseInfo baseInfo){
+        // 更新应用基础信息
+        baseInfo.setInfoStatus(1);
+        baseInfo.setCheckUser("admin");
+        baseInfo.setCheckTime(String.valueOf(DateUtils.getTimestamp()));
+        baseInfoMapper.updateBaseInfo(baseInfo);
+
+        // 给申请注册应用信息的用户发送系统消息
+        AppBaseInfo appBaseInfo = baseInfoMapper.queryAppBaseInfoById(appid);
+        String toUser = baseInfoMapper.queryUsernameById(appBaseInfo.getCreateBy());
+        TemplateMessageDTO message = new TemplateMessageDTO();
+        message.setAppId("0");
+        message.setToUser(toUser);
+        message.setTemplateCode("app_examineAndapprove");
+        Map<String, String> templateParam = new HashMap<>();
+        templateParam.put("resultText","应用"+appBaseInfo.getName()+"注册审核通过");
+        message.setTemplateParam(templateParam);
+        sysBaseApi.sendTemplateAnnouncement(message);
+    }
+
+    // 授予应用相关用户(管理员 开发负责人 运维负责人等)访问应用一级菜单权限
+    private void AfterCheckSaveUserPermission(AppBaseInfo appBaseInfo, String permissionid){
+        sysUserPermissionService.save(getSysUserPermission(appBaseInfo.getAdmin(), permissionid));
+        if (!Objects.equals(appBaseInfo.getBusinessUser(), "")){} sysUserPermissionService.save(getSysUserPermission(appBaseInfo.getBusinessUser(), permissionid));
+        if (!Objects.equals(appBaseInfo.getDevelopUser(), "")) sysUserPermissionService.save(getSysUserPermission(appBaseInfo.getDevelopUser(), permissionid));
+        if (!Objects.equals(appBaseInfo.getRequirementUser(), "")) sysUserPermissionService.save(getSysUserPermission(appBaseInfo.getBusinessUser(), permissionid));
+    }
+
+    private SysUserPermission getSysUserPermission(String username, String permissionId) {
+        String userId = customMapper.queryUserIdByUsername(username);
+        SysUserPermission sysUserPermission = new SysUserPermission();
+        sysUserPermission.setUserId(userId);
+        sysUserPermission.setPermissionId(permissionId);
+        return sysUserPermission;
+    }
+
     // 应用注册 撤销后续处理(删除插入的数据)
     @Override
     public void afterUnsendAppRegisterFlow(long workID) {
@@ -756,4 +759,10 @@ public class AppmanageServiceImpl implements AppmanageService {
             customMapper.deleteAppUserInfoNotLogic(appid);
         }
     }
+
+    @Override
+    public Boolean AppNameIsExist(String appName) {
+        Integer i = customMapper.checkAppNameIsExist(appName);
+        return i!= null;
+    }
 }

+ 78 - 8
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/util/AppManageUtil.java

@@ -7,19 +7,13 @@ import org.jeecg.common.system.util.JwtUtil;
 import org.jeecg.common.util.RedisUtil;
 import org.jeecg.common.util.SpringContextUtils;
 import org.jeecg.modules.client.AppManage.WorkFlowClient;
-import org.jeecg.modules.system.entity.AppmanageEntity.APP_Register_workFlow_FormEntity;
-import org.jeecg.modules.system.entity.AppmanageEntity.AppBaseInfo;
-import org.jeecg.modules.system.entity.AppmanageEntity.AppDocInfo;
-import org.jeecg.modules.system.entity.AppmanageEntity.AppEnvInfo;
+import org.jeecg.modules.system.entity.AppmanageEntity.*;
 import org.jeecg.modules.system.mapper.SysUserMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 功能描述 应用管理工具类
@@ -68,6 +62,82 @@ public class AppManageUtil {
         return appRegisterWorkFlowForm;
     }
 
+    public AppBaseInfo AppRegisterWorkFlowFormEntityToBaseInfo(APP_Register_workFlow_FormEntity appRegisterWorkFlowForm){
+        AppBaseInfo appBaseInfo = new AppBaseInfo();
+        appBaseInfo.setId(appRegisterWorkFlowForm.getId());
+        appBaseInfo.setName(appRegisterWorkFlowForm.getName());
+        appBaseInfo.setType(appRegisterWorkFlowForm.getType());
+        appBaseInfo.setStatus(appRegisterWorkFlowForm.getStatus());
+        appBaseInfo.setAdmin(appRegisterWorkFlowForm.getAdmin());
+        appBaseInfo.setBusinessUser(appRegisterWorkFlowForm.getBusinessUser());
+        appBaseInfo.setRequirementUser(appRegisterWorkFlowForm.getRequirementUser());
+        appBaseInfo.setDevelopUser(appRegisterWorkFlowForm.getDevelopUser());
+        appBaseInfo.setOperationUser(appRegisterWorkFlowForm.getOperationUser());
+        appBaseInfo.setMenuInfo(appRegisterWorkFlowForm.getMenuInfo());
+        appBaseInfo.setDescr(appRegisterWorkFlowForm.getDescr());
+        return appBaseInfo;
+    }
+
+    public AppDocInfo AppRegisterWorkFlowFormEntityToDocInfo(APP_Register_workFlow_FormEntity appRegisterWorkFlowForm){
+        AppDocInfo appDocInfo = new AppDocInfo();
+        appDocInfo.setAppid(appRegisterWorkFlowForm.getId());
+        appDocInfo.setRequirement(appRegisterWorkFlowForm.getRequirement());
+        appDocInfo.setDesign(appRegisterWorkFlowForm.getDesign());
+        appDocInfo.setDev(appRegisterWorkFlowForm.getDev());
+        appDocInfo.setInstructions(appRegisterWorkFlowForm.getInstructions());
+        appDocInfo.setTest(appRegisterWorkFlowForm.getTest());
+        appDocInfo.setOther(appRegisterWorkFlowForm.getOther());
+        return appDocInfo;
+    }
+
+    public AppEditEnvInfoEntity AppRegisterWorkFlowFormEntityToEnvInfo(APP_Register_workFlow_FormEntity appRegisterWorkFlowForm){
+        AppEditEnvInfoEntity appEditEnvInfoEntity = new AppEditEnvInfoEntity();
+        appEditEnvInfoEntity.setAppid(appRegisterWorkFlowForm.getId());
+        AppEnvInfo appEnvInfo = new AppEnvInfo();
+        appEnvInfo.setAppid(appRegisterWorkFlowForm.getId());
+        // 设置测试环境信息
+        if (appRegisterWorkFlowForm.getTest_leadingIp()!=null){
+            appEnvInfo.setEnv("test");
+            appEnvInfo.setLeadingIp(appRegisterWorkFlowForm.getTest_leadingIp());
+            appEnvInfo.setBackendIp(appRegisterWorkFlowForm.getTest_backendIp());
+            appEnvInfo.setBackupFrequency(appRegisterWorkFlowForm.getTest_backupFrequency());
+            appEnvInfo.setBackupLocation(appRegisterWorkFlowForm.getTest_backupLocation());
+            appEnvInfo.setCodeUrl(appRegisterWorkFlowForm.getTest_codeUrl());
+            appEnvInfo.setConfigurationFile(appRegisterWorkFlowForm.getTest_configurationFile());
+            appEnvInfo.setDatabaseInfo(appRegisterWorkFlowForm.getTest_databaseInfo());
+            appEditEnvInfoEntity.getEnvInfo().add(appEnvInfo);
+        }
+
+        if (appRegisterWorkFlowForm.getProd_leadingIp()!=null){
+            // 设置生产环境信息
+            appEnvInfo.setEnv("prod");
+            appEnvInfo.setLeadingIp(appRegisterWorkFlowForm.getProd_leadingIp());
+            appEnvInfo.setBackendIp(appRegisterWorkFlowForm.getProd_backendIp());
+            appEnvInfo.setBackupFrequency(appRegisterWorkFlowForm.getProd_backupFrequency());
+            appEnvInfo.setBackupLocation(appRegisterWorkFlowForm.getProd_backupLocation());
+            appEnvInfo.setCodeUrl(appRegisterWorkFlowForm.getProd_codeUrl());
+            appEnvInfo.setConfigurationFile(appRegisterWorkFlowForm.getProd_configurationFile());
+            appEnvInfo.setDatabaseInfo(appRegisterWorkFlowForm.getProd_databaseInfo());
+            appEditEnvInfoEntity.getEnvInfo().add(appEnvInfo);
+        }
+
+
+        if (appRegisterWorkFlowForm.getDev_leadingIp()!=null){
+            // 设置开发环境信息
+            appEnvInfo.setEnv("dev");
+            appEnvInfo.setLeadingIp(appRegisterWorkFlowForm.getDev_leadingIp());
+            appEnvInfo.setBackendIp(appRegisterWorkFlowForm.getDev_backendIp());
+            appEnvInfo.setBackupFrequency(appRegisterWorkFlowForm.getDev_backupFrequency());
+            appEnvInfo.setBackupLocation(appRegisterWorkFlowForm.getDev_backupLocation());
+            appEnvInfo.setCodeUrl(appRegisterWorkFlowForm.getDev_codeUrl());
+            appEnvInfo.setConfigurationFile(appRegisterWorkFlowForm.getDev_configurationFile());
+            appEnvInfo.setDatabaseInfo(appRegisterWorkFlowForm.getDev_databaseInfo());
+            appEditEnvInfoEntity.getEnvInfo().add(appEnvInfo);
+        }
+
+        return appEditEnvInfoEntity;
+    }
+
     public static String getTemporaryToken() {
         RedisUtil redisUtil = SpringContextUtils.getBean(RedisUtil.class);
         //模拟登录生成临时Token

+ 0 - 1
jeecg-boot/jeecg-server-cloud/jflow-cloud-start/src/main/java/org/jeecg/JeecgJflowCloudApplication.java

@@ -26,7 +26,6 @@ public class JeecgJflowCloudApplication implements CommandLineRunner {
         for (String beanName : beanNames) {
             System.out.println(beanName);
         }
-        System.out.println("lalalala");
     }
 
     /**

+ 3 - 3
jeecg-boot/jflow-core/src/main/java/bp/difference/client/SystemClient.java

@@ -2,15 +2,15 @@ package bp.difference.client;
 
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
 @FeignClient(value = "jeecg-system")
 public interface SystemClient {
 
     // 应用注册审核结束,对应用相关信息的后续处理
-    @GetMapping("/sys/applicationInfo/afterAppCheckPass")
-    <T> void afterAppCheckPass(@RequestParam("appid") String appid,
-                           @RequestParam("formData") T formData);
+    @PostMapping("/sys/applicationInfo/afterAppCheckPass")
+    void afterAppCheckPass(long id);
 
     // 注册应用流程撤销 后续处理的微服务调用
     @GetMapping("/sys/applicationInfo/afterUnsendAppRegisterFlow")

+ 26 - 0
jeecg-boot/jflow-core/src/main/java/bp/sys/BuessUnitAfterAppCheckPass.java

@@ -0,0 +1,26 @@
+package bp.sys;
+
+import bp.difference.BeanUtils;
+import bp.difference.client.SystemClient;
+import bp.sys.BuessUnitBase;
+/**
+ * 功能描述 BuessUnitAfterAppCheckPass
+ *
+ * @author: scott
+ * @date: 2024年12月17日 PM 3:50
+ */
+public class BuessUnitAfterAppCheckPass extends BuessUnitBase {
+
+    @Override
+    public String getTitle() {
+        return "应用审核通过后续处理";
+    }
+
+    @Override
+    public String DoIt()  {
+        SystemClient systemClient = BeanUtils.getBean(SystemClient.class);
+        systemClient.afterAppCheckPass(this.WorkID);
+        System.out.println("乌拉");
+        return null;
+    }
+}

+ 20 - 1
jeecg-boot/jflow-core/src/main/java/bp/sys/base/Glo.java

@@ -196,13 +196,32 @@ public class Glo
 	 */
 	public static BuessUnitBase GetBuessUnitEntityByEnName(String enName)
 	{
+		switch (enName){
+			case "业务单元测试":
+				enName = "bp.demo.BuessUnitDemo";
+				break;
+			case "应用审核通过后续处理":
+				enName = "bp.sys.BuessUnitAfterAppCheckPass";
+				break;
+			default:
+		}
 		if (Htable_BuessUnit == null || Htable_BuessUnit.isEmpty())
 		{
 			Htable_BuessUnit = new Hashtable();
 			ArrayList<BuessUnitBase> al = ClassFactory.GetObjects("BP.Sys.BuessUnitBase");
 			for (BuessUnitBase en : al)
 			{
-				Htable_BuessUnit.put(en.toString(), en);
+				int atIndex = en.toString().lastIndexOf('@');
+
+				if (atIndex != -1) {
+					String result = en.toString().substring(0, atIndex);
+					System.out.println(result);
+					Htable_BuessUnit.put(result, en);
+				} else {
+					System.out.println(en); // 如果没有找到@,则输出原始字符串
+					Htable_BuessUnit.put(en.toString(), en);
+				}
+
 			}
 		}
 

+ 11 - 12
jeecg-boot/jflow-core/src/main/java/bp/wf/WorkNode.java

@@ -9681,7 +9681,7 @@ public class WorkNode {
 				this.setStopFlow(true);
 				this.getHisGenerWorkFlow().setWFState(WFState.Complete);
 				this.rptGe.setWFState(WFState.Complete);
-				MicroserviceCall(); // 流程结束需要进行后续处理调用的微服务
+//				MicroserviceCall(); // 流程结束需要进行后续处理调用的微服务
 				String msg = this.getHisWorkFlow().DoFlowOver(ActionType.FlowOver, "流程已经走到最后一个节点,流程成功结束。", this.getHisNode(), this.rptGe);
 				this.addMsg(SendReturnMsgFlag.End, msg);
 			}
@@ -10545,16 +10545,15 @@ public class WorkNode {
 	}
 
 	private void MicroserviceCall(){
-		UserTokenContext.setToken(getTemporaryToken());
-		String tag = this.rptGe.getRow().GetValStrByKey("workFlowType");
-		switch (tag){
-			case "App_Register":  // 应用注册审批流程
-				SystemClient systemClient = BeanUtils.getBean(SystemClient.class);
-				String appid = this.rptGe.getRow().GetValStrByKey("id");
-				systemClient.afterAppCheckPass(appid, this.rptGe.getRow());
-				break;
-		}
-		UserTokenContext.remove();
+//		String tag = this.rptGe.getRow().GetValStrByKey("workFlowType");
+//		switch (tag){
+//			case "App_Register":  // 应用注册审批流
+//				SystemClient systemClient = BeanUtils.getBean(SystemClient.class);
+//				String appid = this.rptGe.getRow().GetValStrByKey("id");
+//				UserTokenContext.setToken(getTemporaryToken());
+//				systemClient.afterAppCheckPass(appid, this.rptGe.getRow());
+//				UserTokenContext.remove();
+//				break;
+//		}
 	}
-		///#endregion
 }

+ 1 - 9
jeecg-boot/jflow-core/src/main/java/bp/wf/httphandler/WF_Comm.java

@@ -4120,8 +4120,8 @@ public class WF_Comm extends DirectoryPageBase
 		ht.put("CustomerNo", SystemConfig.getCustomerNo());
 		ht.put("CustomerName", SystemConfig.getCustomerName());
 		ht.put("IsAdmin", WebUser.getIsAdmin() == true ? 1 : 0);
+//		ht.put("IsAdmin", 1);
 		ht.put("Token", WebUser.getToken()); //token.
-
 		ht.put("Tel", WebUser.getTel());
 		ht.put("OrgNo", WebUser.getOrgNo());
 		ht.put("OrgName", WebUser.getOrgName());
@@ -4137,15 +4137,7 @@ public class WF_Comm extends DirectoryPageBase
 		{
 			ht.put("IsAuthorize", "0");
 		}
-
-		//每次访问表很消耗资源.
-		//Port.WFEmp emp = new BP.Port.WFEmp(WebUser.getNo());
-		//ht.Add("Theme", emp.GetParaString("Theme"));
-
-
-		//增加运行模式. add by zhoupeng 2020.03.10 适应saas模式.
 		ht.put("CCBPMRunModel", SystemConfig.GetValByKey("CCBPMRunModel", "0"));
-
 		return Json.ToJson(ht);
 	}
 

+ 1 - 1
jeecgboot-vue3/.env.production

@@ -16,7 +16,7 @@ VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
 VITE_GLOB_API_URL=/jeecgboot
 
 #后台接口全路径地址(必填)
-VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
+VITE_GLOB_DOMAIN_URL=http://10.200.1.115:9999
 
 # 接口父路径前缀
 VITE_GLOB_API_URL_PREFIX=

+ 1 - 1
jeecgboot-vue3/jflow-vue-core/assets/GPN_Emp-57dc0d67.js

@@ -16,4 +16,4 @@ var c=Object.defineProperty;var N=(o,t,u)=>t in o?c(o,t,{enumerable:!0,configura
   #### \u5E2E\u52A9
    - \u4E5F\u79F0\u4E3A\u7B80\u5355\u9879\u76EE\u6216\u8005\u4E0D\u786E\u5B9A\u6027\u9879\u76EE\uFF0C\u6CA1\u6709\u6A21\u5F0F\u7684\u4E34\u65F6\u6027\u4EFB\u52A1\uFF0C
     - \u6BD4\u5982 \u7533\u62A5\u77E5\u8BC6\u4EA7\u6743\uFF0C\u627E\u51E0\u4E2A\u4EBA\u534F\u4F5C\u5B8C\u6210\uFF0C\u53EF\u4EE5\u6709\u56FA\u5B9A\u65F6\u9650\uFF0C\u6BCF\u4E2A\u5B50\u4EFB\u52A1\u5206\u7ED9\u4E0D\u540C\u7684\u4EBA\uFF0C\u5904\u7406\u5B8C\u6BD5\u540E\u9700\u8981\u6C47\u62A5\uFF0C\u8BA4\u53EF\uFF0C\u786E\u8BA4\uFF0C\u53EF\u4EE5\u6811\u5F62\u7ED3\u6784\u7684\u5206\u53D1\u6536\u56DE\uFF0C\u5B50\u4EFB\u52A1\u6570\u4E0D\u786E\u5B9A\u3002
-  `);this.PageTitle="\u65B0\u5EFA\u4EBA\u5458"}Init(){return m(this,null,function*(){if(i.IsAdmin==!1){w.error("err@\u60A8\u597D:"+i.Name+",\u975E\u7BA1\u7406\u5458\u7528\u6237\u4E0D\u80FD\u67E5\u770B.");return}const u=this.RequestVal("DeptNo");yield new y(u).Retrieve(),this.AddGroup("A","\u9009\u62E9\u65B9\u5F0F"),this.TextBox2_NameNo("Emp","\u65B0\u5EFA\u4EBA\u5458",this.Daily,"","\u767B\u5F55\u8D26\u53F7","\u4EBA\u5458\u540D\u79F0",""),this.SelectItemsByTreeEns("Imp","\u5BFC\u5165\u4EBA\u5458",this.Daily,!0,n.srcDeptLazily,"0",n.srcEmpLazily,"@No=\u8D26\u53F7@Name=\u540D\u79F0@Tel=\u7535\u8BDD")})}GenerSorts(){return m(this,null,function*(){return Promise.resolve([])})}Save_TextBox_X(u,p,C,A,s){return m(this,null,function*(){if(u==="Emp"){const r=this.RequestVal("DeptNo"),E=A,e=C,F=new d;return i.CCBPMRunModel==2&&(F.UserId=E,F.OrgNo=i.OrgNo),F.No=E,(yield F.IsExits())==!0?new D(a.Error,"\u4EBA\u5458\u7F16\u53F7["+E+"],\u5DF2\u7ECF\u5B58\u5728."):(F.FK_Dept=r,F.Name=e,yield F.Insert(),new D(a.GoToUrl,f.UrlEn("TS.Port.Emp",E)))}if(u==="Imp"){const r=this.RequestVal("DeptNo");C.split(",").forEach(e=>m(this,null,function*(){const F=new G(r+"_"+e);(yield F.RetrieveFromDBSources())==0&&(F.FK_Dept=r,F.FK_Emp=e,yield F.Insert())}))}})}}export{Cu as GPN_Emp};
+  `);this.PageTitle="\u65B0\u5EFA\u4EBA\u5458"}Init(){return m(this,null,function*(){/**if(i.IsAdmin==!1){w.error("err@\u60A8\u597D:"+i.Name+",\u975E\u7BA1\u7406\u5458\u7528\u6237\u4E0D\u80FD\u67E5\u770B.");return}**/const u=this.RequestVal("DeptNo");yield new y(u).Retrieve(),this.AddGroup("A","\u9009\u62E9\u65B9\u5F0F"),this.TextBox2_NameNo("Emp","\u65B0\u5EFA\u4EBA\u5458",this.Daily,"","\u767B\u5F55\u8D26\u53F7","\u4EBA\u5458\u540D\u79F0",""),this.SelectItemsByTreeEns("Imp","\u5BFC\u5165\u4EBA\u5458",this.Daily,!0,n.srcDeptLazily,"0",n.srcEmpLazily,"@No=\u8D26\u53F7@Name=\u540D\u79F0@Tel=\u7535\u8BDD")})}GenerSorts(){return m(this,null,function*(){return Promise.resolve([])})}Save_TextBox_X(u,p,C,A,s){return m(this,null,function*(){if(u==="Emp"){const r=this.RequestVal("DeptNo"),E=A,e=C,F=new d;return i.CCBPMRunModel==2&&(F.UserId=E,F.OrgNo=i.OrgNo),F.No=E,(yield F.IsExits())==!0?new D(a.Error,"\u4EBA\u5458\u7F16\u53F7["+E+"],\u5DF2\u7ECF\u5B58\u5728."):(F.FK_Dept=r,F.Name=e,yield F.Insert(),new D(a.GoToUrl,f.UrlEn("TS.Port.Emp",E)))}if(u==="Imp"){const r=this.RequestVal("DeptNo");C.split(",").forEach(e=>m(this,null,function*(){const F=new G(r+"_"+e);(yield F.RetrieveFromDBSources())==0&&(F.FK_Dept=r,F.FK_Emp=e,yield F.Insert())}))}})}}export{Cu as GPN_Emp};

+ 1 - 1
jeecgboot-vue3/jflow-vue-core/assets/GPN_Emp-c3891a55.js

@@ -16,4 +16,4 @@ var c=Object.defineProperty;var N=(o,t,u)=>t in o?c(o,t,{enumerable:!0,configura
   #### \u5E2E\u52A9
    - \u4E5F\u79F0\u4E3A\u7B80\u5355\u9879\u76EE\u6216\u8005\u4E0D\u786E\u5B9A\u6027\u9879\u76EE\uFF0C\u6CA1\u6709\u6A21\u5F0F\u7684\u4E34\u65F6\u6027\u4EFB\u52A1\uFF0C
     - \u6BD4\u5982 \u7533\u62A5\u77E5\u8BC6\u4EA7\u6743\uFF0C\u627E\u51E0\u4E2A\u4EBA\u534F\u4F5C\u5B8C\u6210\uFF0C\u53EF\u4EE5\u6709\u56FA\u5B9A\u65F6\u9650\uFF0C\u6BCF\u4E2A\u5B50\u4EFB\u52A1\u5206\u7ED9\u4E0D\u540C\u7684\u4EBA\uFF0C\u5904\u7406\u5B8C\u6BD5\u540E\u9700\u8981\u6C47\u62A5\uFF0C\u8BA4\u53EF\uFF0C\u786E\u8BA4\uFF0C\u53EF\u4EE5\u6811\u5F62\u7ED3\u6784\u7684\u5206\u53D1\u6536\u56DE\uFF0C\u5B50\u4EFB\u52A1\u6570\u4E0D\u786E\u5B9A\u3002
-  `);this.PageTitle="\u65B0\u5EFA\u4EBA\u5458"}Init(){return m(this,null,function*(){if(i.IsAdmin==!1){w.error("err@\u60A8\u597D:"+i.Name+",\u975E\u7BA1\u7406\u5458\u7528\u6237\u4E0D\u80FD\u67E5\u770B.");return}const u=this.RequestVal("DeptNo");yield new y(u).Retrieve(),this.AddGroup("A","\u9009\u62E9\u65B9\u5F0F"),this.TextBox2_NameNo("Emp","\u65B0\u5EFA\u4EBA\u5458",this.Daily,"","\u767B\u5F55\u8D26\u53F7","\u4EBA\u5458\u540D\u79F0",""),this.SelectItemsByTreeEns("Imp","\u5BFC\u5165\u4EBA\u5458",this.Daily,!0,n.srcDeptLazily,"0",n.srcEmpLazily,"@No=\u8D26\u53F7@Name=\u540D\u79F0@Tel=\u7535\u8BDD")})}GenerSorts(){return m(this,null,function*(){return Promise.resolve([])})}Save_TextBox_X(u,p,C,A,s){return m(this,null,function*(){if(u==="Emp"){const r=this.RequestVal("DeptNo"),E=A,e=C,F=new d;return i.CCBPMRunModel==2&&(F.UserId=E,F.OrgNo=i.OrgNo),F.No=E,(yield F.IsExits())==!0?new D(a.Error,"\u4EBA\u5458\u7F16\u53F7["+E+"],\u5DF2\u7ECF\u5B58\u5728."):(F.FK_Dept=r,F.Name=e,yield F.Insert(),new D(a.GoToUrl,f.UrlEn("TS.Port.Emp",E)))}if(u==="Imp"){const r=this.RequestVal("DeptNo");C.split(",").forEach(e=>m(this,null,function*(){const F=new G(r+"_"+e);(yield F.RetrieveFromDBSources())==0&&(F.FK_Dept=r,F.FK_Emp=e,yield F.Insert())}))}})}}export{Cu as GPN_Emp};
+  `);this.PageTitle="\u65B0\u5EFA\u4EBA\u5458"}Init(){return m(this,null,function*(){/**if(i.IsAdmin==!1){w.error("err@\u60A8\u597D:"+i.Name+",\u975E\u7BA1\u7406\u5458\u7528\u6237\u4E0D\u80FD\u67E5\u770B.");return}**/const u=this.RequestVal("DeptNo");yield new y(u).Retrieve(),this.AddGroup("A","\u9009\u62E9\u65B9\u5F0F"),this.TextBox2_NameNo("Emp","\u65B0\u5EFA\u4EBA\u5458",this.Daily,"","\u767B\u5F55\u8D26\u53F7","\u4EBA\u5458\u540D\u79F0",""),this.SelectItemsByTreeEns("Imp","\u5BFC\u5165\u4EBA\u5458",this.Daily,!0,n.srcDeptLazily,"0",n.srcEmpLazily,"@No=\u8D26\u53F7@Name=\u540D\u79F0@Tel=\u7535\u8BDD")})}GenerSorts(){return m(this,null,function*(){return Promise.resolve([])})}Save_TextBox_X(u,p,C,A,s){return m(this,null,function*(){if(u==="Emp"){const r=this.RequestVal("DeptNo"),E=A,e=C,F=new d;return i.CCBPMRunModel==2&&(F.UserId=E,F.OrgNo=i.OrgNo),F.No=E,(yield F.IsExits())==!0?new D(a.Error,"\u4EBA\u5458\u7F16\u53F7["+E+"],\u5DF2\u7ECF\u5B58\u5728."):(F.FK_Dept=r,F.Name=e,yield F.Insert(),new D(a.GoToUrl,f.UrlEn("TS.Port.Emp",E)))}if(u==="Imp"){const r=this.RequestVal("DeptNo");C.split(",").forEach(e=>m(this,null,function*(){const F=new G(r+"_"+e);(yield F.RetrieveFromDBSources())==0&&(F.FK_Dept=r,F.FK_Emp=e,yield F.Insert())}))}})}}export{Cu as GPN_Emp};

File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_Dept2Emp-1adb0fbf.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_Dept2Emp-f31e8155.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FlowSort2Flow-211db7d6.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FlowSort2Flow-f61eb57f.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FrmSort2Frm-1d2f3bc0.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_FrmSort2Frm-98f3d82c.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_TemplateSort2Template-63b1f209.js


File diff suppressed because it is too large
+ 0 - 0
jeecgboot-vue3/jflow-vue-core/assets/TreeEns_TemplateSort2Template-b5f22e48.js


+ 1 - 1
jeecgboot-vue3/src/api/sys/user.ts

@@ -73,7 +73,7 @@ export function jflowLoginApi(params, mode: ErrorMessageMode = 'modal') {
       url: Api.jflowLogin + '?userNo=' + params.userNo + '&privateKey=' + params.privateKey +'&jeecgToken=' + params.jeecgToken,
     },
     {
-      errorMessageMode: mode,
+      errorMessageMode: "none",
     }
   );
 }

+ 45 - 19
jeecgboot-vue3/src/components/Lttc/BaseService/LTTCBaseServiceAdvancedSearch.vue

@@ -1,13 +1,20 @@
 <!-- AdvancedSearch.vue -->
 <template>
-  <a-collapse v-model:activeKey="activeKey"accordion style="background-color: white;">
-    <a-collapse-panel key="1" >
+  <a-collapse v-model:activeKey="activeKey" accordion style="background-color: white;">
+    <a-collapse-panel key="1">
       <template #header>
         高级查询方案:
-        <a-button type="link" v-for="(item, index) in savedQueries.slice(0, visibleCount)"
-                  :key="index" @click.stop="() => handleQueryNameClick(item)"  @dblclick.stop="resetQuery">
-          {{ truncateText(item.queryName) }}
-        </a-button>
+        <a-tooltip placement="top" v-for="(item, index) in savedQueries.slice(0, visibleCount)">
+          <template #title>
+            <span>双击取消查询 |<a-button type="link" @click.stop="() =>  handleDrawDelete(item.id)"
+                                          danger>删除方案</a-button></span>
+          </template>
+          <a-button :type="isActive(index) ? 'primary' : 'link'"
+                    :key="index" @click.stop="() => handleQueryNameClick(index,item)"
+                    @dblclick.stop="resetQuery">
+            {{ truncateText(item.queryName) }}
+          </a-button>
+        </a-tooltip>
         <a-button type="link" v-if="savedQueries.length > visibleCount" @click.stop="quickQuery">更多
         </a-button>
       </template>
@@ -29,7 +36,7 @@
             </a-col>
             <!-- 查询列选择 -->
             <a-col :span="6">
-              <a-form-item  style="width:90%">
+              <a-form-item style="width:90%">
                 <a-select v-model:value="query.column" class="a-select" placeholder="请选择查询列">
                   <a-select-option class="a-select" v-for="col in fieldOptions" :key="col.value"
                                    :value="col.value">
@@ -40,7 +47,7 @@
             </a-col>
             <!-- 查询条件选择 -->
             <a-col :span="3">
-              <a-form-item  style="width:90%">
+              <a-form-item style="width:90%">
                 <a-select v-model:value="query.condition" placeholder="请选择查询条件"
                           class="a-select">
                   <a-select-option class="a-select" v-for="condition in conditionOptions"
@@ -53,7 +60,7 @@
             </a-col>
             <!-- 查询内容输入,根据列的类型显示不同的输入控件 -->
             <a-col :span="6">
-              <a-form-item  style="width:90%">
+              <a-form-item style="width:90%">
                 <template v-if="getColumnType(query.column).toLowerCase() === 'date'">
                   <a-date-picker v-model:value="query.term" format="YYYY-MM-DD"
                                  placeholder="请选择日期"/>
@@ -79,9 +86,10 @@
             <!-- 添加和删除查询条件按钮 -->
             <a-col :span="6">
               <a-form-item>
-                <a-button v-if="queries.length > 1" @click="removeQuery(index)" type="danger" style="margin-right: 1vh">删除
+                <a-button v-if="queries.length > 1" @click="removeQuery(index)" type="danger"
+                          style="margin-right: 1vh">删除
                 </a-button>
-                <a-button @click="addQuery" type="primary"  style="margin-right: 1vh">添加</a-button>
+                <a-button @click="addQuery" type="primary" style="margin-right: 1vh">添加</a-button>
               </a-form-item>
             </a-col>
           </a-row>
@@ -89,8 +97,8 @@
         <!-- 提交、保存和加载查询条件按钮 -->
         <a-form-item>
           <a-button @click="resetQuery" type="default" style="margin-right: 1vh">重置</a-button>
-          <a-button type="primary" html-type="submit"  style="margin-right: 1vh">查询</a-button>
-          <a-button @click="showModal" type="default"  style="margin-right: 1vh">保存</a-button>
+          <a-button type="primary" html-type="submit" style="margin-right: 1vh">查询</a-button>
+          <a-button @click="showModal" type="default" style="margin-right: 1vh">保存</a-button>
         </a-form-item>
       </a-form>
       <!--查询高级查询方案-->
@@ -112,7 +120,7 @@
         >
           <template #renderItem="{ item }">
             <a-list-item>
-              <a-button type="link" @click="() => handleQueryNameClick(item)">
+              <a-button type="link" @click="() => handleQueryNameClick(index,item)">
                 {{ truncateText(item.queryName) }}
               </a-button>
               <a-button danger type="link" @click="() => handleDrawDelete(item.id)">删除
@@ -152,7 +160,9 @@ import {Form, Input, Button, Select, DatePicker, Modal} from 'ant-design-vue';
 import {useUserStore} from '/@/store/modules/user';
 import {saveOrUpdate, listByUrlAndUser, deleteOne} from './LTTCBaseServiceAdvancedSearch.api';
 import {JDictSelectTag} from '/@/components/Form';
-// 查询条件数组
+
+const activeIndex = ref<any>(null);
+// 查询条件数
 const visibleCount = ref<number>(3);
 // 用户信息
 const userStore = useUserStore();
@@ -187,9 +197,13 @@ const quickQuery = () => {
  * 重置高级查询方案
  */
 const resetQuery = () => {
+  // 选中的按钮取消
+  activeIndex.value = null
+  // 查询条件取消
   queries.value = [{column: '', condition: 'like', term: '', mode: 'and'}];
   console.log("props.rawData");
   console.log(props.rawData);
+  // 返回查询数据喝状态
   emit('update:searchedDataReset');
   emit('update:searchedData', resetData.value);
 
@@ -197,7 +211,7 @@ const resetQuery = () => {
 const onDrawerClose = () => {
   drawerVisible.value = false;
 }
-const activeKey= ref<string | null>(null);
+const activeKey = ref<string | null>(null);
 // 查询条件选项
 const conditionOptions = ref([
   {value: 'gte', label: '大于等于'},
@@ -219,7 +233,7 @@ const modeOptions = ref([
 ]);
 
 // 查询条件数组
-const queries = ref([{column: '', condition: 'like', term: '', mode: 'and'}]);
+const queries = ref<any>([{column: '', condition: 'like', term: '', mode: 'and'}]);
 
 // 保存的查询条件
 const savedQueries = ref([]); // 这里存储保存的查询条件
@@ -438,7 +452,10 @@ const saveQuery = async (name: String) => {
   console.log("saveQuery");
   console.log(param);
   // 实现保存当前查询条件的逻辑
-  await saveOrUpdate(param, false)
+  await saveOrUpdate(param, false).then(res => {
+    //更新查询方案数据
+    loadQuery();
+  });
 };
 
 
@@ -503,6 +520,8 @@ const handleCancel = () => {
  */
 const deleteQuery = (id: any) => {
   savedQueries.value = savedQueries.value.filter(item => item.id !== id);
+  // 重新加载默认查询方案数据
+  resetQuery();
 }
 /**
  * 后端删除高级查询记录
@@ -530,8 +549,10 @@ const changeQuery = async (id) => {
  * 加载查询条件
  * @param item
  */
-const handleQueryNameClick = async (item: any) => {
+const handleQueryNameClick = async (index: any, item: any) => {
+  activeIndex.value = index;
   onDrawerClose();
+  resetQuery
   await changeQuery(item.id);
   handleSearch();
 };
@@ -554,6 +575,11 @@ const truncateText = (text: string): string => {
 
   return result;
 };
+
+function isActive(index) {
+  return activeIndex.value === index;
+}
+
 // 在组件挂载时加载选中的查询条件
 onMounted(() => {
   loadQuery();

+ 5 - 7
jeecgboot-vue3/src/store/modules/user.ts

@@ -173,18 +173,13 @@ export const useUserStore = defineStore({
 
     // 登录到jflow
     async loginToJFlow(username: string, mode: ErrorMessageMode) {
-      console.log("执行了登录JFlow方法:"+this.getToken)
-      //jflowtoken
-      const jflowLoginInfo = await jflowLoginApi({ userNo: username, privateKey: import.meta.env.VITE_APP_JFLOW_KEY, jeecgToken: this.getToken }, mode);
-      console.dir(jflowLoginInfo)
       try {
+        const jflowLoginInfo = await jflowLoginApi({ userNo: username, privateKey: import.meta.env.VITE_APP_JFLOW_KEY, jeecgToken: this.getToken }, mode);
         const jflowInfo = JSON.parse(jflowLoginInfo as string);
         const { Token } = jflowInfo;
-        console.log("登录到JFlow并拿到Token:"+Token)
         this.setJFlowToken(Token);
       } catch (err: any) {
-        console.error(err.toString());
-        message.error('jflow登录失败,请重新登录');
+        if (err.response.status === 503) message.warning('Jflow服务不可用');
       }
     },
     /**
@@ -204,6 +199,7 @@ export const useUserStore = defineStore({
         this.setToken(token);
         this.setTenant(userInfo.loginTenantId);
         // await this.loginToJFlow(userInfo.username, mode);
+
         return this.afterLoginAction(goHome, data);
       } catch (error) {
         return Promise.reject(error);
@@ -229,6 +225,8 @@ export const useUserStore = defineStore({
       if (!this.getToken) return null;
       //获取用户信息
       const userInfo = await this.getUserInfoAction();
+      const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
+      await delay(3000); // 延迟3秒
       const sessionTimeout = this.sessionTimeout;
       if (sessionTimeout) {
         this.setSessionTimeout(false);

+ 4 - 1
jeecgboot-vue3/src/views/appmanage/AppBaseInfo.api.ts

@@ -32,6 +32,7 @@ enum Api {
     isAppAdminOrDevOrOpe = '/sys/applicationInfo/isAppAdminOrDevOrOpe',
     isAppAdmin = '/sys/applicationInfo/isAppAdmin',
     checkMenuInfoisExist = '/sys/permission/checkPermDuplication',
+    checkAppNameisExist = '/sys/applicationInfo/appNameIsExist',
     workFlowTest1 = '/sys/applicationInfo/test1',
     workFlowTest2 = '/sys/applicationInfo/test2'
 }
@@ -45,7 +46,9 @@ export const JFlow_Test1=()=>{
 export const checkMenuInfoisExist=(params)=>{
     return defHttp.get({url: Api.checkMenuInfoisExist+"?url="+params+"&alwaysShow="+false},  { errorMessageMode: false, successMessageMode: false })
 }
-
+export const checkAppNameisExist=(params)=>{
+    return defHttp.get({url: Api.checkAppNameisExist+"?appName="+params},  { errorMessageMode: false, successMessageMode: false })
+}
 export const isAppAdmin=()=>{
   return defHttp.get({url: Api.isAppAdmin})
 }

+ 6 - 8
jeecgboot-vue3/src/views/appmanage/AppInfoList.vue

@@ -252,6 +252,8 @@ import { message, Modal } from 'ant-design-vue';
 import Description from '@/components/Description/src/Description.vue'
 import { useDescription } from '/@/components/Description';
 import {menuInfoisshow} from "@/views/appmanage/addForm/data";
+import {useLocaleStore} from "@/store/modules/locale";
+import Cookies from 'js-cookie';
 const isLoading = ref(true);
 const columns = ref(listColumns2)
 const modalVisible = ref(false);
@@ -264,7 +266,6 @@ const infoDetailVisible = ref(false)
 const appname = ref('')
 const addType = ref('')
 const isInfoDeptUserTag = ref(false)
-const showAddAppInfoButtonTag = ref(false)
 
 const formState = reactive<FormState>({
   appname: '',
@@ -332,8 +333,7 @@ export default defineComponent({
       appname,
       addFormDraftData,
       isLoading,
-      isInfoDeptUserTag,
-      showAddAppInfoButtonTag
+      isInfoDeptUserTag
     }
   },
 
@@ -341,12 +341,10 @@ export default defineComponent({
     // 清除草稿数据缓存
     columns.value = listColumns2
     // 检查当前进入应用管理的用户是否为信息部用户
-    const isInfoDeptUser = await isInfoUser()
-    isInfoDeptUserTag.value = isInfoDeptUser
-    // 是否显示注册应用按钮
-    showAddAppInfoButtonTag.value = await isAppAdmin()
+    var departid = Cookies.get("FK_Dept")
+    isInfoDeptUserTag.value = departid == '1817753406332235777'
 
-    if (isInfoDeptUser){
+    if (isInfoDeptUserTag.value){
       columns.value.splice(11, 4)
     }else {
       // 防止点击平台的右上角刷新时再执行一次,多删除几个列

+ 3 - 4
jeecgboot-vue3/src/views/appmanage/addForm/Step1.vue

@@ -77,7 +77,7 @@ import {useUserStore} from '@/store/modules/user'
 //设置变量储存登陆人信息
   const userStore = useUserStore();
   step1Schemas.forEach(item =>{
-    if (item.field === 'admin') item.defaultValue = userStore.userInfo.id
+    if (item.field === 'admin') item.defaultValue = userStore.userInfo.username
   })
 
 const [register, {setFieldsValue, getFieldsValue, validate }]  = useForm({
@@ -185,14 +185,13 @@ const appAdminUseroptions = ref<SelectProps['options']>([]);
 
       // 初始化表单数据
       async initBaseForm(value) {
-        console.log("表单一设置数据")
         // 设置信息部用户
         await selectUserByDept('1817753406332235777').then(res => {
           let infoUserData = []
           res.forEach(item=>{
             const obj = {
               label: item.realname,
-              value: item.id
+              value: item.username
             }
             infoUserData.push(obj)
           })
@@ -205,7 +204,7 @@ const appAdminUseroptions = ref<SelectProps['options']>([]);
           res.forEach(item=>{
             const obj = {
               label: item.realname,
-              value: item.id
+              value: item.username
             }
             infoUserData.push(obj)
           })

+ 17 - 11
jeecgboot-vue3/src/views/appmanage/addForm/Step4.vue

@@ -39,16 +39,10 @@
       <div class="appUserOperateitem">
         <a-button @click="clearConditionAndData">重 置</a-button>
       </div>
-      <div>
-      <!-- 作为编辑页面时显示   -->
-      <a-button type="primary"
-                :disabled="adduserCount===0"
-                @click="removeUserInfo('edit')"
-                v-if="!tag"  v-show="!uncheckTag">移 除</a-button>
-      </div>
+
       <!-- 作为编辑页面时显示  -->
-      <div class="appUserOperateitem" style="margin-left: 10%">
-        <span v-if="!tag" style="padding-right: 5%; white-space: nowrap"> <b>新增用户:{{(newlyUserData as any).length}}</b> </span>
+      <div class="appUserOperateitem" style="margin-left: 11%">
+        <span v-show="!uncheckTag" v-if="!tag" style="padding-right: 5%; white-space: nowrap"> <b>新增用户:{{(newlyUserData as any).length}}</b> </span>
         <a-button type="primary" :disabled="uncheckTag" @click="handleOpen" v-if="!uncheckTag&&!tag">添加用户</a-button>
         <AppUserSelectByDepModal ref="addNewUser" :rowKey="rowKey" v-if="!uncheckTag&&!tag"
                                  :appid="appid" :appuserids="appUserids" @register="regModal"
@@ -134,15 +128,24 @@
                      :scroll="{y: 230}" :pagination="false" size="small"
                       class="rightuserTableClass">
               <template #title>
+                <div style="display: flex; align-items: center">
                 <b>移除用户:{{(removeUserData as any).length}}</b>
-                <a-popconfirm
+
+                  <!-- 作为编辑页面时显示   -->
+                  <a-button type="primary"
+                            :disabled="adduserCount===0"
+                            @click="removeUserInfo('edit')"
+                            v-if="!tag"  v-show="!uncheckTag" style="margin-left: 5%">移 除</a-button>
+                   <a-popconfirm
                     title="你确定要移除全部信息吗?"
                     ok-text="是"
                     cancel-text="否"
                     @confirm="removeAllUserInfo('editForm_removeUserData')"
                     @cancel="cancel">
-                <a-button style="margin-left: 40%" v-show="(removeUserData as any).length>0">全部移除</a-button>
+                  <a-button style="margin-left: 5%" v-show="(removeUserData as any).length>0">全部移除</a-button>
                 </a-popconfirm>
+                </div>
+             
               </template>
               <template #bodyCell="{ column, record }">
                 <template v-if="column.dataIndex === 'action'">
@@ -334,6 +337,8 @@ export default defineComponent({
       }
       await queryAppUser(params).then(response => {
         this.pagination.total = response.total
+        console.log("查询用户信息")
+        console.dir(response)
         isEdit.value = response.isEdit
         response.userinfos.forEach(item =>{
           const itemObj = {
@@ -398,6 +403,7 @@ export default defineComponent({
         console.log("作为编辑表单的初始化:"+this.appid)
         await this.clearConditionAndData()
       }
+      console.log("此时的tag:"+tag.value)
     },
 
     cancelAdd(){

+ 14 - 3
jeecgboot-vue3/src/views/appmanage/addForm/data.tsx

@@ -1,7 +1,7 @@
 import { FormSchema } from '/@/components/Form';
 import {ref} from "vue";
 import {ComponentTypes} from "@/views/system/menu/menu/menu.data";
-import {checkMenuInfoisExist} from "@/views/appmanage/AppBaseInfo.api";
+import {checkAppNameisExist, checkMenuInfoisExist} from "@/views/appmanage/AppBaseInfo.api";
 
 
 export const menuInfoisshow = ref(false)
@@ -29,7 +29,6 @@ const isValidIpAddress = (ip) => {
 };
 
 export const checkMenuInfo = async (_rule, value, callback) => {
-  console.log("菜单信息:"+value)
   const res = await checkMenuInfoisExist(value)
   if (res === '该值可用!') {
     callback(); // 校验通过
@@ -38,12 +37,24 @@ export const checkMenuInfo = async (_rule, value, callback) => {
   }
 };
 
+// 检查应用名字是否已经存在
+export const checkAppName = async (_rule, value, callback) => {
+  const res = await checkAppNameisExist(value)
+  if (res === '检查通过') {
+    callback(); // 校验通过
+  } else {
+    callback(new Error(res)); // 校验失败
+  }
+};
+
 export const step1Schemas: FormSchema[] = [
   {
     field: 'name',
     component: 'Input',
     label: '应用名称',
     required: true,
+    ifShow: ({ values }) => !(values.component === ComponentTypes.IFrame && values.internalOrExternal),
+    rules:[{ validator: checkAppName, trigger: 'blur'}],
     componentProps: {
       placeholder:"请输入应用名称"
     },
@@ -122,7 +133,7 @@ export const step1Schemas: FormSchema[] = [
     label: '业务对接人',
     componentProps: {
       isRadioSelection: true,
-      rowKey:'id'
+      rowKey:'username'
     },
     colProps: {
       span: 8,

+ 70 - 8
jeecgboot-vue3/src/views/system/depart/components/DepartLeftTree.vue

@@ -42,7 +42,7 @@
       </template>
     </a-alert>
     <a-spin :spinning="loading">
-      <a-input-search placeholder="按部门名称搜索…" style="margin-bottom: 10px" @search="onSearch" />
+      <a-input-search placeholder="按部门名称搜索…" style="margin-bottom: 10px" v-model:value="searchValue" @search="onSearch" />
       <!--组织机构树-->
       <template v-if="treeData.length > 0">
         <a-tree
@@ -57,6 +57,7 @@
           v-model:expandedKeys="expandedKeys"
           @check="onCheck"
           @select="onSelect"
+          @expand="onExpand"
         >
           <template #title="{ key: treeKey, title, dataRef }">
             <a-dropdown :trigger="['contextmenu']">
@@ -86,12 +87,12 @@
       </template>
       <a-empty v-else description="暂无数据" />
     </a-spin>
-    <DepartFormModal :rootTreeData="treeData" @register="registerModal" @success="loadRootTreeData" />
+    <DepartFormModal :rootTreeData="treeData" @register="registerModal" @success="onSaveSuccess" />
   </a-card>
 </template>
 
 <script lang="ts" setup>
-  import { inject, nextTick, ref, unref } from 'vue';
+import {inject, nextTick, ref, unref, watch} from 'vue';
   import { useModal } from '/@/components/Modal';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { useMethods } from '/@/hooks/system/useMethods';
@@ -128,10 +129,20 @@
   const isUnfold = ref(false)
   // 需要展开
   const needExpand = ref<string[]>([])
+  //部门搜索值
+  const searchValue = ref('');
 
   // 注册 modal
   const [registerModal, { openModal }] = useModal();
 
+  //保存成功后执行
+  function onSaveSuccess() {
+    checkedKeys.value = [];
+    expandedKeys.value = [];
+    isUnfold.value = false;
+    loadRootTreeData();
+  }
+
   // 加载顶级部门信息
   async function loadRootTreeData() {
     try {
@@ -198,7 +209,7 @@
             //选中全部子节点
             checkedKeys.value.push(resultElement.key)
           }
-        onExpand()
+        expandNode()
       }
       emit('rootTreeData', treeData.value);
     } catch (e) {
@@ -254,7 +265,12 @@
     }
     const record = { parentId: data.id };
     openModal(true, { isUpdate: false, isChild: true, record });
+    isUnfold.value = false
   }
+  //监听搜索框内值的变化
+  watch(searchValue, (newVal) => {
+    onSearch(newVal)
+  });
 
   // 搜索事件
   async function onSearch(value: string) {
@@ -271,6 +287,7 @@
         loading.value = false;
       }
     } else {
+      isUnfold.value = false
       loadRootTreeData();
     }
     searchKeyword.value = value;
@@ -279,11 +296,21 @@
   // 树复选框选择事件
   function onCheck(checked, info) {
     // console.log(info.node.children.length)
+    // console.log(info.checked)
+    // console.log(info.node)
+
+    // console.log(checked)
+
     if (Array.isArray(checked)) {
       checkedKeys.value = checked;
     } else {
       checkedKeys.value = checked.checked;
     }
+
+    if (!info.checked) {
+      onCheckCancel(info.node)
+    }
+
     // console.log(Array.isArray(checked))
     // console.log(checked)
     // console.log(checked.checked)
@@ -296,7 +323,7 @@
     }
   }
   //展开子节点
-  function onExpand() {
+  function expandNode() {
     needExpand.value.forEach((item) => {
       expandedKeys.value.push(item)
     })
@@ -305,13 +332,34 @@
   //已加载的节点也选中
   function onCheckedKeys(node) {
     for (let i = 0; i < node.children.length; i++) {
+      //去重,防止重复选中
+      if (checkedKeys.value.indexOf(node.children[i].key) === -1) {
+        checkedKeys.value.push(node.children[i].key)
+      }
+      // checkedKeys.value.push(node.children[i].key)
       expandedKeys.value.push(node.children[i].key)
-      checkedKeys.value.push(node.children[i].key)
       if (node.children[i].children.length > 0) {
         onCheckedKeys(node.children[i])
       }
     }
   }
+
+  //父结点取消选择后,子节点也取消选择
+  function onCheckCancel(node) {
+    console.log('取消选择')
+    for (let i = 0; i < node.children.length; i++) {
+      let index = checkedKeys.value.indexOf(node.children[i].key);
+      if (index !== -1) {
+        checkedKeys.value.splice(index, 1); // 移除选中的键
+      }
+      // expandedKeys.value.push(node.children[i].key)
+      // checkedKeys.value.push(node.children[i].key)
+      if (node.children[i].children.length > 0) {
+        onCheckCancel(node.children[i])
+      }
+    }
+    // console.log(checkedKeys.value)
+  }
 /**
   function onCheck(checked, info) {
     console.log(checked)
@@ -335,7 +383,7 @@
 
   // 树选择事件
   function onSelect(selKeys, event) {
-    console.log('select: ', selKeys, event);
+    // console.log('select: ', selKeys, event);
     if (selKeys.length > 0 && selectedKeys.value[0] !== selKeys[0]) {
       setSelectedKey(selKeys[0], event.selectedNodes[0]);
     } else {
@@ -355,7 +403,14 @@
       try {
         loading.value = true;
         await deleteBatchDepart({ ids: idList.join(',') }, confirm);
+        isUnfold.value = false
         await loadRootTreeData();
+        await idList.forEach((id) => {
+          let index = checkedKeys.value.indexOf(id);
+          if (index !== -1) {
+            checkedKeys.value.splice(index, 1); // 移除选中的键
+          }
+        })
       } finally {
         loading.value = false;
       }
@@ -387,17 +442,23 @@
 
   function onImportXls(d) {
     handleImportXls(d, Api.importExcelUrl, () => {
+      isUnfold.value = false
       loadRootTreeData();
     });
   }
   function onInitializationImportExcel(d) {
     handleImportXls(d, Api.initializationImportExcel, () => {
+      isUnfold.value = false
       loadRootTreeData();
     })
   }
 
   function onExportXls() {
-    handleExportXls('部门信息', Api.exportXlsUrl);
+    handleExportXls('部门信息', Api.exportXlsUrl, {selections: checkedKeys.value.toString()});
+  }
+
+  function onExpand() {
+    isUnfold.value = false
   }
 
   //setup生命周期
@@ -405,5 +466,6 @@
 
   defineExpose({
     loadRootTreeData,
+    onSaveSuccess,
   });
 </script>

+ 2 - 2
jeecgboot-vue3/src/views/system/depart/index.vue

@@ -44,7 +44,7 @@
 
   // 左侧树选择后触发
   function onTreeSelect(data) {
-    console.log('onTreeSelect: ', data);
+    // console.log('onTreeSelect: ', data);
     departData.value = data;
   }
 
@@ -54,7 +54,7 @@
   }
 
   function onSuccess() {
-    leftTree.value.loadRootTreeData();
+    leftTree.value.onSaveSuccess();
   }
 </script>
 

+ 183 - 149
jeecgboot-vue3/src/views/system/dict/index.vue

@@ -3,11 +3,19 @@
   <BasicTable @register="registerTable" :rowSelection="rowSelection">
     <!--插槽:table标题-->
     <template #tableTitle>
-      <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
-      <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
-      <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
-      <a-button type="primary" @click="handlerRefreshCache" preIcon="ant-design:sync-outlined"> 刷新缓存</a-button>
-      <a-button type="primary" @click="openRecycleModal(true)" preIcon="ant-design:hdd-outlined"> 回收站</a-button>
+      <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增
+      </a-button>
+      <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出
+      </a-button>
+      <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">
+        导入
+      </j-upload-button>
+      <a-button type="primary" @click="handlerRefreshCache" preIcon="ant-design:sync-outlined">
+        刷新缓存
+      </a-button>
+      <a-button type="primary" @click="openRecycleModal(true)" preIcon="ant-design:hdd-outlined">
+        回收站
+      </a-button>
 
       <a-dropdown v-if="selectedRowKeys.length > 0">
         <template #overlay>
@@ -19,173 +27,199 @@
           </a-menu>
         </template>
         <a-button
-          >批量操作
+        >批量操作
           <Icon icon="ant-design:down-outlined"></Icon>
         </a-button>
       </a-dropdown>
     </template>
     <!--操作栏-->
     <template #action="{ record }">
-      <TableAction :actions="getTableAction(record)" />
+      <TableAction :actions="getTableAction(record)"/>
     </template>
   </BasicTable>
   <!--字典弹窗-->
-  <DictModal @register="registerModal" @success="handleSuccess" />
+  <DictModal @register="registerModal" @success="handleSuccess"/>
   <!--字典配置抽屉-->
-  <DictItemList @register="registerDrawer" />
+  <DictItemList @register="registerDrawer"/>
   <!--回收站弹窗-->
-  <DictRecycleBinModal @register="registerModal1" @success="reload" />
+  <DictRecycleBinModal @register="registerModal1" @success="reload"/>
 </template>
 
 <script lang="ts" name="system-dict" setup>
-  //ts语法
-  import { ref, computed, unref } from 'vue';
-  import { BasicTable, TableAction } from '/src/components/Table';
-  import { useDrawer } from '/src/components/Drawer';
-  import { useModal } from '/src/components/Modal';
-  import DictItemList from './components/DictItemList.vue';
-  import DictModal from './components/DictModal.vue';
-  import DictRecycleBinModal from './components/DictRecycleBinModal.vue';
-  import { useMessage } from '/src/hooks/web/useMessage';
-  import { removeAuthCache, setAuthCache } from '/src/utils/auth';
-  import { columns, searchFormSchema } from './dict.data';
-  import { list, deleteDict, batchDeleteDict, getExportUrl, getImportUrl, refreshCache, queryAllDictItems } from './dict.api';
-  import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum';
-  import { useUserStore } from '/@/store/modules/user';
-
-  const { createMessage } = useMessage();
-  //字典model
-  const [registerModal, { openModal }] = useModal();
-  //字典配置drawer
-  const [registerDrawer, { openDrawer }] = useDrawer();
-  import { useListPage } from '/@/hooks/system/useListPage';
-
-  //回收站model
-  const [registerModal1, { openModal: openRecycleModal }] = useModal();
-
-  // 列表页面公共参数、方法
-  const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
-    designScope: 'dict-template',
-    tableProps: {
-      title: '数据字典',
-      api: list,
-      columns: columns,
-      formConfig: {
-        schemas: searchFormSchema,
-      },
-      actionColumn: {
-        width: 240,
-      },
-    },
-    //update-begin---author:wangshuai ---date:20220616  for:[issues/I5AMDD]导入/导出功能,操作后提示没有传递 export.url/import.url 参数------------
-    exportConfig: {
-      name: '数据字典列表',
-      url: getExportUrl,
+//ts语法
+import {ref, computed, unref} from 'vue';
+import {BasicTable, TableAction} from '/src/components/Table';
+import {useDrawer} from '/src/components/Drawer';
+import {useModal} from '/src/components/Modal';
+import DictItemList from './components/DictItemList.vue';
+import DictModal from './components/DictModal.vue';
+import DictRecycleBinModal from './components/DictRecycleBinModal.vue';
+import {useMessage} from '/src/hooks/web/useMessage';
+import {removeAuthCache, setAuthCache} from '/src/utils/auth';
+import {columns, searchFormSchema} from './dict.data';
+import {
+  list,
+  deleteDict,
+  batchDeleteDict,
+  getExportUrl,
+  getImportUrl,
+  refreshCache,
+  queryAllDictItems
+} from './dict.api';
+import {DB_DICT_DATA_KEY} from '/src/enums/cacheEnum';
+import {useUserStore} from '/@/store/modules/user';
+
+const {createMessage} = useMessage();
+//字典model
+const [registerModal, {openModal}] = useModal();
+//字典配置drawer
+const [registerDrawer, {openDrawer}] = useDrawer();
+import {useListPage} from '/@/hooks/system/useListPage';
+
+//回收站model
+const [registerModal1, {openModal: openRecycleModal}] = useModal();
+
+// 列表页面公共参数、方法
+const {prefixCls, tableContext, onExportXls, onImportXls} = useListPage({
+  designScope: 'dict-template',
+  tableProps: {
+    title: '数据字典',
+    api: list,
+    columns: columns,
+    formConfig: {
+      schemas: searchFormSchema,
     },
-    importConfig: {
-      url: getImportUrl,
+    actionColumn: {
+      width: 240,
     },
-    //update-end---author:wangshuai ---date:20220616  for:[issues/I5AMDD]导入/导出功能,操作后提示没有传递 export.url/import.url 参数--------------
+  },
+  //update-begin---author:wangshuai ---date:20220616  for:[issues/I5AMDD]导入/导出功能,操作后提示没有传递 export.url/import.url 参数------------
+  exportConfig: {
+    name: '数据字典列表',
+    url: getExportUrl,
+  },
+  importConfig: {
+    url: getImportUrl,
+  },
+  //update-end---author:wangshuai ---date:20220616  for:[issues/I5AMDD]导入/导出功能,操作后提示没有传递 export.url/import.url 参数--------------
+});
+
+//注册table数据
+const [registerTable, {reload, updateTableDataRecord}, {
+  rowSelection,
+  selectedRowKeys
+}] = tableContext;
+
+/**
+ * 新增事件
+ */
+function handleCreate() {
+  openModal(true, {
+    isUpdate: false,
   });
+}
 
-  //注册table数据
-  const [registerTable, { reload, updateTableDataRecord }, { rowSelection, selectedRowKeys }] = tableContext;
+/**
+ * 编辑事件
+ */
+async function handleEdit(record: Recordable) {
+  openModal(true, {
+    record,
+    isUpdate: true,
+  });
+}
 
-  /**
-   * 新增事件
-   */
-  function handleCreate() {
-    openModal(true, {
-      isUpdate: false,
-    });
-  }
-  /**
-   * 编辑事件
-   */
-  async function handleEdit(record: Recordable) {
-    openModal(true, {
-      record,
-      isUpdate: true,
-    });
-  }
-  /**
-   * 详情
-   */
-  async function handleDetail(record) {
-    openModal(true, {
-      record,
-      isUpdate: true,
-    });
-  }
-  /**
-   * 删除事件
-   */
-  async function handleDelete(record) {
-    await deleteDict({ id: record.id }, reload);
-  }
-  /**
-   * 批量删除事件
-   */
-  async function batchHandleDelete() {
-    await batchDeleteDict({ ids: selectedRowKeys.value }, reload);
-  }
-  /**
-   * 成功回调
-   */
-  function handleSuccess({ isUpdate, values }) {
-    if (isUpdate) {
-      updateTableDataRecord(values.id, values);
-    } else {
-      reload();
-    }
+/**
+ * 详情
+ */
+async function handleDetail(record) {
+  openModal(true, {
+    record,
+    isUpdate: true,
+  });
+}
+
+/**
+ * 删除事件
+ */
+async function handleDelete(record) {
+  await deleteDict({id: record.id}, reload);
+  let number = selectedRowKeys.value.indexOf(record.id);
+  if (number !== -1) {
+    selectedRowKeys.value.splice(number, 1);
   }
-  /**
-   * 刷新缓存
-   */
-  async function handlerRefreshCache() {
-    const result = await refreshCache();
-    if (result.success) {
-      const res = await queryAllDictItems();
-      removeAuthCache(DB_DICT_DATA_KEY);
-      // update-begin--author:liaozhiyang---date:20230908---for:【QQYUN-6417】生产环境字典慢的问题
-      const userStore = useUserStore();
-      userStore.setAllDictItems(res.result);
-      // update-end--author:liaozhiyang---date:20230908---for:【QQYUN-6417】生产环境字典慢的问题
-      createMessage.success('刷新缓存完成!');
-    } else {
-      createMessage.error('刷新缓存失败!');
-    }
+}
+
+/**
+ * 批量删除事件
+ */
+async function batchHandleDelete() {
+  await batchDeleteDict({ids: selectedRowKeys.value}, () => {
+    selectedRowKeys.value = [];
+    reload();
+  });
+}
+
+/**
+ * 成功回调
+ */
+function handleSuccess({isUpdate, values}) {
+  if (isUpdate) {
+    updateTableDataRecord(values.id, values);
+  } else {
+    reload();
   }
-  /**
-   * 字典配置
-   */
-  function handleItem(record) {
-    openDrawer(true, {
-      id: record.id,
-    });
+}
+
+/**
+ * 刷新缓存
+ */
+async function handlerRefreshCache() {
+  const result = await refreshCache();
+  if (result.success) {
+    const res = await queryAllDictItems();
+    removeAuthCache(DB_DICT_DATA_KEY);
+    // update-begin--author:liaozhiyang---date:20230908---for:【QQYUN-6417】生产环境字典慢的问题
+    const userStore = useUserStore();
+    userStore.setAllDictItems(res.result);
+    // update-end--author:liaozhiyang---date:20230908---for:【QQYUN-6417】生产环境字典慢的问题
+    createMessage.success('刷新缓存完成!');
+  } else {
+    createMessage.error('刷新缓存失败!');
   }
-  /**
-   * 操作栏
-   */
-  function getTableAction(record) {
-    return [
-      {
-        label: '编辑',
-        onClick: handleEdit.bind(null, record),
-      },
-      {
-        label: '字典配置',
-        onClick: handleItem.bind(null, record),
-      },
-      {
-        label: '删除',
-        popConfirm: {
-          title: '确定删除吗?',
-          confirm: handleDelete.bind(null, record),
-        },
+}
+
+/**
+ * 字典配置
+ */
+function handleItem(record) {
+  openDrawer(true, {
+    id: record.id,
+  });
+}
+
+/**
+ * 操作栏
+ */
+function getTableAction(record) {
+  return [
+    {
+      label: '编辑',
+      onClick: handleEdit.bind(null, record),
+    },
+    {
+      label: '字典配置',
+      onClick: handleItem.bind(null, record),
+    },
+    {
+      label: '删除',
+      popConfirm: {
+        title: '确定删除吗?',
+        confirm: handleDelete.bind(null, record),
       },
-    ];
-  }
+    },
+  ];
+}
 </script>
 
 <style scoped></style>

+ 9 - 0
jeecgboot-vue3/src/views/system/user/UserDrawer.vue

@@ -140,6 +140,15 @@
     //update-begin-author:taoyan date:2022-5-24 for: VUEN-1117【issue】0523周开源问题
     setProps({ disabled: !showFooter.value });
     //update-end-author:taoyan date:2022-5-24 for: VUEN-1117【issue】0523周开源问题
+
+    //组织
+    console.log(data.deptId)
+    console.log(isUpdate)
+    if (data.deptId !== null && !unref(isUpdate)) {
+      console.log(data.deptId.id)
+      const depts = [data.deptId.id]
+      await setFieldsValue({ selecteddeparts: depts });
+    }
   });
   //获取标题
   const getTitle = computed(() => {

+ 14 - 0
jeecgboot-vue3/src/views/system/user/UserRecycleBinModal.vue

@@ -87,6 +87,7 @@
    * 还原事件
    */
   async function handleRevert(record) {
+    await clearCheckedKeys(record.id)
     await putRecycleBin({ userIds: record.id }, reload);
     emit('success');
   }
@@ -100,8 +101,21 @@
    * 删除事件
    */
   async function handleDelete(record) {
+    await clearCheckedKeys(record.id)
     await deleteRecycleBin({ userIds: record.id }, reload);
   }
+
+  //清除复选框勾选
+  function clearCheckedKeys(id) {
+    if (id.toString().includes(',')) {
+      checkedKeys.value = []
+    } else {
+      let index = checkedKeys.value.indexOf(id);
+      if (index !== -1) {
+        checkedKeys.value.splice(index, 1);
+      }
+    }
+  }
   /**
    * 批量删除事件
    */

+ 16 - 4
jeecgboot-vue3/src/views/system/user/index.vue

@@ -5,7 +5,7 @@
         <a-card :bordered="false" style="height: 100%">
           <a-spin :spinning="loading">
             <a-input-search placeholder="按部门名称搜索…" style="margin-bottom: 10px"
-                            @search="onSearch"/>
+                            @search="onSearch" v-model:value="searchValue" />
             <!--组织机构树-->
             <template v-if="treeData.length > 0">
               <a-tree
@@ -27,7 +27,7 @@
         </a-card>
       </div>
       <div style="display: flex; flex-direction: column; width: 1350px;">
-        <div style="flex: 1; padding-top: 10px;padding-left: 10px; padding-right: 10px;">
+        <div style="padding-top: 10px;padding-left: 10px; padding-right: 10px;">
           <a-card :bordered="false" :bodyStyle = cardBodyStyle>
             <LTTCBaseServiceAdvancedSearch
               :fieldOptions="dataFields"
@@ -97,7 +97,7 @@
 
 <script lang="ts" name="system-user" setup>
   //ts语法
-  import {ref, computed, unref, nextTick} from 'vue';
+  import {ref, computed, unref, nextTick, watch} from 'vue';
   import { BasicTable, TableAction, ActionItem } from '/@/components/Table';
   import UserDrawer from './UserDrawer.vue';
   import UserRecycleBinModal from './UserRecycleBinModal.vue';
@@ -159,6 +159,8 @@
   const rawData = ref<any[]>([]);
   // 高级查询参数
   const queries = ref([]);
+  //搜索值
+  const searchValue = ref('');
 
   //高级查询参数
   const dataFields = [
@@ -386,6 +388,7 @@
    */
   function handleCreate() {
     openDrawer(true, {
+      deptId: currentDepart.value,
       isUpdate: false,
       showFooter: true,
       tenantSaas: false,
@@ -422,6 +425,10 @@
       return;
     }
     await deleteUser({ id: record.id }, reload);
+    let number = selectedRowKeys.value.indexOf(record.id);
+    if (number !== -1) {
+      selectedRowKeys.value.splice(number, 1);
+    }
   }
   /**
    * 批量删除事件
@@ -593,13 +600,18 @@
    * 导出Excel
    */
   function handleExportExcel() {
-    handleExportXls("用户列表", getExportUrl, { queries: JSON.stringify(queries.value)})
+    handleExportXls("用户列表", getExportUrl, {queries: JSON.stringify(queries.value), selections: selectedRowKeys.value.toString()})
 
   }
   const cardBodyStyle = {
     padding: '0px',
   };
 
+  //监听搜索框内值的变化
+  watch(searchValue, (newVal) => {
+    onSearch(newVal);
+  });
+
 
 </script>
 

+ 6 - 1
jeecgboot-vue3/src/views/system/user/user.data.ts

@@ -291,6 +291,8 @@ export const formSchema: FormSchema[] = [
       dictCode: 'sex',
       placeholder: '请选择性别',
       stringToNumber: true,
+      allowClear: false,
+      showChooseOption: false,
     },
   },
   {
@@ -341,7 +343,10 @@ export const formPasswordSchema: FormSchema[] = [
     label: '用户账号',
     field: 'username',
     component: 'Input',
-    componentProps: { readOnly: true },
+    componentProps: {
+      readOnly: true,
+      allowClear: false
+    },
   },
   {
     label: '登录密码',

Some files were not shown because too many files changed in this diff