Forráskód Böngészése

Merge branch 'master' of http://49.233.37.222:3000/wjm/mec-cloud_IntelligentManufacturing_CRM

Zn 1 éve
szülő
commit
2c770dd3dd
40 módosított fájl, 1690 hozzáadás és 160 törlés
  1. 65 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysActivationLogController.java
  2. 4 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
  3. 17 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysTenantController.java
  4. 1 1
      ruoyi-admin/src/main/resources/application-druid.yml
  5. 7 0
      ruoyi-common/pom.xml
  6. 11 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysTenant.java
  7. 22 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
  8. 43 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
  9. 1 1
      ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
  10. 64 0
      ruoyi-system/src/main/java/com/ruoyi/system/domain/SysActivationCodeLog.java
  11. 13 1
      ruoyi-system/src/main/java/com/ruoyi/system/domain/SysBpmNodeScript.java
  12. 50 0
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysActivationCodeLogMapper.java
  13. 50 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysActivationCodeLogService.java
  14. 11 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTenantService.java
  15. 70 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ISysActivationCodeLogServiceImpl.java
  16. 151 4
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantServiceImpl.java
  17. 65 0
      ruoyi-system/src/main/resources/mapper/system/SysActivationCodeLogMapper.xml
  18. 7 3
      ruoyi-system/src/main/resources/mapper/system/SysBpmNodeScriptMapper.xml
  19. 3 2
      ruoyi-system/src/main/resources/mapper/system/SysTenantMapper.xml
  20. 3 3
      ruoyi-ui/.env.development
  21. 9 0
      ruoyi-ui/src/api/bpmprocess/process.js
  22. 26 0
      ruoyi-ui/src/api/monitor/activationcode.js
  23. 16 1
      ruoyi-ui/src/api/system/tenant.js
  24. 21 3
      ruoyi-ui/src/utils/bpmn/formDataValidate.js
  25. 38 1
      ruoyi-ui/src/views/bpmprocess/index.vue
  26. 82 24
      ruoyi-ui/src/views/bpmprocess/scriptManage.vue
  27. 7 7
      ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementExecuteUser.vue
  28. 17 8
      ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementGenerations.vue
  29. 142 0
      ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementNormalTask.vue
  30. 103 27
      ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementUnusualTasks.vue
  31. 10 7
      ruoyi-ui/src/views/system/bpmnPro/components/Panel/index.vue
  32. 19 12
      ruoyi-ui/src/views/system/bpmnPro/components/Toolbar/tools/Save.vue
  33. 57 13
      ruoyi-ui/src/views/system/bpmnPro/components/bo-utils/getNodeMsg.js
  34. 89 7
      ruoyi-ui/src/views/system/bpmnPro/components/bo-utils/myFieldUtil.js
  35. 7 1
      ruoyi-ui/src/views/system/bpmnPro/index.vue
  36. 274 0
      ruoyi-ui/src/views/system/tenant/code/index.vue
  37. 69 5
      ruoyi-ui/src/views/system/tenant/index.vue
  38. 14 0
      ruoyi-ui/src/views/tableMange/index.vue
  39. 31 28
      ruoyi-ui/src/views/tablelist/commonTable/listInfo.vue
  40. 1 1
      ruoyi-ui/vue.config.js

+ 65 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysActivationLogController.java

@@ -0,0 +1,65 @@
+package com.ruoyi.web.controller.monitor;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysActivationCodeLog;
+import com.ruoyi.system.service.ISysActivationCodeLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 操作日志记录
+ * 
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/activationlog")
+public class SysActivationLogController extends BaseController
+{
+    @Autowired
+    private ISysActivationCodeLogService iSysActivationCodeLogService;
+
+    @PreAuthorize("@ss.hasPermi('monitor:activationcodelog:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysActivationCodeLog activationCodeLog)
+    {
+        startPage();
+        List<SysActivationCodeLog> list = iSysActivationCodeLogService.selectActivationCodeLogList(activationCodeLog);
+        return getDataTable(list);
+    }
+
+    @Log(title = "操作日志", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('monitor:activationcodelog:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysActivationCodeLog activationCodeLog)
+    {
+        List<SysActivationCodeLog> list = iSysActivationCodeLogService.selectActivationCodeLogList(activationCodeLog);
+        ExcelUtil<SysActivationCodeLog> util = new ExcelUtil<>(SysActivationCodeLog.class);
+        util.exportExcel(response, list, "操作日志");
+    }
+
+    @Log(title = "操作日志", businessType = BusinessType.DELETE)
+    @PreAuthorize("@ss.hasPermi('monitor:activationcodelog:remove')")
+    @DeleteMapping("/{logIds}")
+    public AjaxResult remove(@PathVariable Long[] logIds)
+    {
+        return toAjax(iSysActivationCodeLogService.deleteActivationCodeLogById(logIds));
+    }
+
+    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
+    @PreAuthorize("@ss.hasPermi('monitor:activationcodelog:remove')")
+    @DeleteMapping("/clean")
+    public AjaxResult clean()
+    {
+        iSysActivationCodeLogService.cleanActivationCodeLog();
+        return success();
+    }
+}

+ 4 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@@ -79,6 +79,10 @@ public class SysLoginController {
     public AjaxResult login(@RequestBody LoginBody loginBody) {
         //校验租户状态?生成token
         AjaxResult ajax = AjaxResult.success();
+        String  checkTenantExpirationTimeMsg= loginService.checkTenantExpirationTime(loginBody.getUsername());
+        if(!checkTenantExpirationTimeMsg.isEmpty()){
+            return AjaxResult.error(checkTenantExpirationTimeMsg);
+        }
         // 生成令牌
         String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                 loginBody.getUuid());

+ 17 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysTenantController.java

@@ -112,4 +112,21 @@ public class SysTenantController extends BaseController
     public AjaxResult initTenantMenuData(@PathVariable Long tenantId){
         return sysTenantService.initTenantMenuData(tenantId);
     }
+
+    /**
+     * 生成激活码方法
+     */
+    @GetMapping("/crateTenantCode/{tenantId}/{tenantExpirationTime}")
+    public AjaxResult crateTenantCode(@PathVariable String tenantId,@PathVariable String tenantExpirationTime) throws Exception {
+        return sysTenantService.crateTenantCode(tenantId,tenantExpirationTime);
+    }
+
+    /**
+     * 激活租户
+     */
+    @GetMapping("/activationOperation/{tenantId}/{activationCode}")
+    public AjaxResult activationOperation(@PathVariable String tenantId,@PathVariable String activationCode) throws Exception {
+        return sysTenantService.activationOperation(tenantId,activationCode);
+    }
+
 }

+ 1 - 1
ruoyi-admin/src/main/resources/application-druid.yml

@@ -6,7 +6,7 @@ spring:
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://localhost:3306/ry-vue-call?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                url: jdbc:mysql://192.168.110.15:3306/ry-vue-call?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
                 password: 123456
             # 从库数据源

+ 7 - 0
ruoyi-common/pom.xml

@@ -126,11 +126,18 @@
             <artifactId>javax.servlet-api</artifactId>
         </dependency>
 
+        <!-- lombok-->
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
 
+        <!-- 糊涂工具包-->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.16</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 11 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysTenant.java

@@ -49,6 +49,17 @@ public class SysTenant extends BaseEntity
 
     private DataSource dataSource;
 
+    /** 租户的到期时间 */
+    private String tenantExpirationTime;
+
+    public String getTenantExpirationTime() {
+        return tenantExpirationTime;
+    }
+
+    public void setTenantExpirationTime(String tenantExpirationTime) {
+        this.tenantExpirationTime = tenantExpirationTime;
+    }
+
     public Long getTenantId() {
         return tenantId;
     }

+ 22 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java

@@ -8,6 +8,7 @@ import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
 import org.apache.commons.lang3.time.DateFormatUtils;
 
@@ -188,4 +189,25 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
         return Date.from(zdt.toInstant());
     }
+
+    /**
+     * 日期类型转换 String 转 LocalDateTime
+     */
+
+    public static LocalDateTime toLocalDateTime(String dateTime,String df)
+    {
+        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(df);
+        LocalDateTime localDateTime= LocalDateTime.parse(dateTime, dateTimeFormatter);
+        return localDateTime;
+    }
+
+    /**
+     * 日期类型转换 LocalDateTime 转 String
+     */
+    public static String toLocalDateTimeStr(LocalDateTime dateTime)
+    {
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String dateStr = dateTime.format(fmt);
+        return dateStr;
+    }
 }

+ 43 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -1,6 +1,12 @@
 package com.ruoyi.framework.web.service;
 
 import javax.annotation.Resource;
+
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
+import cn.hutool.crypto.symmetric.SymmetricCrypto;
+import com.ruoyi.common.core.domain.entity.SysTenant;
+import com.ruoyi.system.service.impl.SysTenantServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
@@ -29,6 +35,9 @@ import com.ruoyi.framework.security.context.AuthenticationContextHolder;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
 
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
 /**
  * 登录校验方法
  * 
@@ -52,6 +61,9 @@ public class SysLoginService
     @Autowired
     private ISysConfigService configService;
 
+    @Autowired
+    private SysTenantServiceImpl sysTenantService;
+
     /**
      * 登录验证
      * 
@@ -178,4 +190,35 @@ public class SysLoginService
         sysUser.setLoginDate(DateUtils.getNowDate());
         userService.updateUserProfile(sysUser);
     }
+
+    public String checkTenantExpirationTime(String username) {
+        SysUser user = userService.selectUserByUserName(username);
+        //拿到当前登录用户
+        System.out.println(user);
+        if(!user.getUserName().equals("admin")){
+            //根据租户id查询租户信息
+            SysTenant sysTenant = sysTenantService.selectSysTenantByTenantId(user.getTenantId());
+            if(sysTenant!=null){
+                System.out.println("dfsdfasdfasd");
+            }
+            if(sysTenant.getTenantExpirationTime()==null||sysTenant.getTenantExpirationTime().isEmpty()){
+                return "该用户租户信息并未激活";
+            }
+            SymmetricCrypto symmetricCrypto = new SymmetricCrypto(SymmetricAlgorithm.DES, "sgEsnN6QWq8W7j5H01020304".getBytes());
+            //当前时间
+            LocalDateTime now=LocalDateTime.now();
+            long nowSecond = now.toEpochSecond(ZoneOffset.ofHours(8));
+            //到期时间
+            String LastActiveTimeStr = symmetricCrypto.decryptStr(sysTenant.getTenantExpirationTime(), CharsetUtil.CHARSET_UTF_8);
+            LocalDateTime LastActiveDateTime = DateUtils.toLocalDateTime(LastActiveTimeStr, "yyyy-MM-dd HH:mm:ss");
+            long expirationTimeSecond = LastActiveDateTime.toEpochSecond(ZoneOffset.ofHours(8));
+            //计算时间戳
+            long difference=expirationTimeSecond-nowSecond; //相差的时间数 后边减前边
+            //如果是负数证明已经过期了
+            if(difference<0){
+                return "该用户租户信息已过期";
+            }
+        }
+        return "";
+    }
 }

+ 1 - 1
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java

@@ -215,7 +215,7 @@ public class GenUtils
      */
     public static String replaceText(String text)
     {
-        return RegExUtils.replaceAll(text, "(?:表|若依)", "");
+        return RegExUtils.replaceAll(text, "(?:若依)", "");
     }
 
     /**

+ 64 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysActivationCodeLog.java

@@ -0,0 +1,64 @@
+package com.ruoyi.system.domain;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import java.util.Date;
+
+/**
+ * @author hmc
+ * @date 2023-10-24 13:19
+ * @Description:
+ */
+public class SysActivationCodeLog extends BaseEntity {
+
+    /** 日志id */
+    private int logId;
+    /** 激活码生成时间**/
+    private Date generationTime;
+    /** 操作人**/
+    private String operator;
+    /** ip地址**/
+    private String ipAddress;
+    /**备注**/
+    private String note;
+
+    public int getLogId() {
+        return logId;
+    }
+
+    public void setLogId(int logId) {
+        this.logId = logId;
+    }
+
+    public Date getGenerationTime() {
+        return generationTime;
+    }
+
+    public void setGenerationTime(Date generationTime) {
+        this.generationTime = generationTime;
+    }
+
+    public String getOperator() {
+        return operator;
+    }
+
+    public void setOperator(String operator) {
+        this.operator = operator;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    public String getNote() {
+        return note;
+    }
+
+    public void setNote(String note) {
+        this.note = note;
+    }
+}

+ 13 - 1
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysBpmNodeScript.java

@@ -36,6 +36,9 @@ public class SysBpmNodeScript extends BaseEntity
     /** 脚本描述 */
     private String scriptDescription;
 
+    /** 行业分类 */
+    private String industryType;
+
     /** 删除标志(0:否;1:是) */
     private String delFlag;
 
@@ -107,7 +110,15 @@ public class SysBpmNodeScript extends BaseEntity
         this.delFlag = delFlag;
     }
 
-    public String getDelFlag() 
+    public String getIndustryType() {
+        return industryType;
+    }
+
+    public void setIndustryType(String industryType) {
+        this.industryType = industryType;
+    }
+
+    public String getDelFlag()
     {
         return delFlag;
     }
@@ -122,6 +133,7 @@ public class SysBpmNodeScript extends BaseEntity
             .append("scriptFunctionCode", getScriptFunctionCode())
             .append("scriptType", getScriptType())
             .append("scriptDescription", getScriptDescription())
+            .append("industryType",getIndustryType())
             .append("delFlag", getDelFlag())
             .append("createBy", getCreateBy())
             .append("createTime", getCreateTime())

+ 50 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysActivationCodeLogMapper.java

@@ -0,0 +1,50 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.system.domain.SysActivationCodeLog;
+import com.ruoyi.system.domain.SysOperLog;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author hmc
+ * @date 2023-10-24 13:27
+ * @Description:
+ */
+@Mapper
+public interface SysActivationCodeLogMapper {
+
+    /**
+     * 新增数据源
+     */
+    int insertDataSource(SysActivationCodeLog sysActivationCodeLog);
+
+    /**
+     * 查询系统操作日志集合
+     *
+     * @param sysActivationCodeLog 操作日志对象
+     * @return 操作日志集合
+     */
+    public List<SysActivationCodeLog> selectActivationCodeLogList(SysActivationCodeLog sysActivationCodeLog);
+
+    /**
+     * 批量删除系统操作日志
+     *
+     * @param logIds 需要删除的操作日志ID
+     * @return 结果
+     */
+    public int deleteActivationCodeLogByIds(Long[] logIds);
+
+    /**
+     * 查询操作日志详细
+     *
+     * @param logId 操作ID
+     * @return 操作日志对象
+     */
+    public SysOperLog selectActivationCodeLogById(Long logId);
+
+    /**
+     * 清空操作日志
+     */
+    public void cleanActivationCodeLog();
+}

+ 50 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysActivationCodeLogService.java

@@ -0,0 +1,50 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysActivationCodeLog;
+import com.ruoyi.system.domain.SysOperLog;
+
+import java.util.List;
+
+/**
+ * 操作日志 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysActivationCodeLogService
+{
+    /**
+     * 新增激活码操作日志
+     * 
+     * @param sysActivationCodeLog 操作日志对象
+     */
+    public void insertActivationCodeLog(SysActivationCodeLog sysActivationCodeLog);
+
+    /**
+     * 查询系统操作日志集合
+     * 
+     * @param sysActivationCodeLog 操作日志对象
+     * @return 操作日志集合
+     */
+    public List<SysActivationCodeLog> selectActivationCodeLogList(SysActivationCodeLog sysActivationCodeLog);
+
+    /**
+     * 批量删除系统操作日志
+     * 
+     * @param logIds 需要删除的操作日志ID
+     * @return 结果
+     */
+    public int deleteActivationCodeLogById(Long[] logIds);
+
+    /**
+     * 查询操作日志详细
+     * 
+     * @param logId 操作ID
+     * @return 操作日志对象
+     */
+    public SysOperLog selectActivationCodeLogById(Long logId);
+
+    /**
+     * 清空操作日志
+     */
+    public void cleanActivationCodeLog();
+}

+ 11 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTenantService.java

@@ -65,4 +65,15 @@ public interface ISysTenantService
      * 初始化租户菜单关联表数据(租户默认菜单)
      */
     AjaxResult initTenantMenuData(Long tenantId);
+
+
+    /**
+     * 创建租户激活码
+     */
+    AjaxResult crateTenantCode( String tenantId,String tenantExpirationTime) throws Exception;
+
+    /**
+     * 激活租户
+     */
+    AjaxResult activationOperation( String tenantId,String activationCode) throws Exception;
 }

+ 70 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ISysActivationCodeLogServiceImpl.java

@@ -0,0 +1,70 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.system.domain.SysActivationCodeLog;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.mapper.SysActivationCodeLogMapper;
+import com.ruoyi.system.service.ISysActivationCodeLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author lucky
+ * @date 2023-10-26 13:36
+ * @Description:
+ */
+
+@Service
+public class ISysActivationCodeLogServiceImpl implements ISysActivationCodeLogService {
+
+
+    @Autowired
+    SysActivationCodeLogMapper sysActivationCodeLogMapper;
+
+    /**
+     * 新增操作日志
+     * @param sysActivationCodeLog 操作日志对象
+     */
+    @Override
+    public void insertActivationCodeLog(SysActivationCodeLog sysActivationCodeLog) {
+        sysActivationCodeLogMapper.insertDataSource(sysActivationCodeLog);
+    }
+
+    /**
+     * 查询激活码操作日志集合
+     * @param sysActivationCodeLog 操作日志对象
+     */
+    @Override
+    public List<SysActivationCodeLog> selectActivationCodeLogList(SysActivationCodeLog sysActivationCodeLog) {
+       return sysActivationCodeLogMapper.selectActivationCodeLogList(sysActivationCodeLog);
+    }
+
+    /**
+     * 批量删除激活码操作日志
+     * @param logIds 需要删除的操作日志ID
+     * @return 结果
+     */
+    @Override
+    public int deleteActivationCodeLogById(Long[] logIds) {
+        return sysActivationCodeLogMapper.deleteActivationCodeLogByIds(logIds);
+    }
+
+    /**
+     * 查询激活码操作日志详细
+     * @param logId 操作ID
+     * @return 操作日志对象
+     */
+    @Override
+    public SysOperLog selectActivationCodeLogById(Long logId) {
+        return sysActivationCodeLogMapper.selectActivationCodeLogById(logId);
+    }
+
+    /**
+     * 清空激活码操作日志
+     */
+    @Override
+    public void cleanActivationCodeLog() {
+        sysActivationCodeLogMapper.cleanActivationCodeLog();
+    }
+}

+ 151 - 4
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantServiceImpl.java

@@ -5,21 +5,32 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
+import cn.hutool.crypto.symmetric.SymmetricCrypto;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.system.domain.SysActivationCodeLog;
 import com.ruoyi.system.domain.SysTenantMenu;
-import com.ruoyi.system.mapper.SysMenuMapper;
-import com.ruoyi.system.mapper.SysTenantMenuMapper;
-import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.mapper.*;
 import com.ruoyi.system.service.ISysUserService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
-import com.ruoyi.system.mapper.SysTenantMapper;
 import com.ruoyi.common.core.domain.entity.SysTenant;
 import com.ruoyi.system.service.ISysTenantService;
 import org.springframework.transaction.annotation.Transactional;
@@ -48,6 +59,12 @@ public class SysTenantServiceImpl implements ISysTenantService
     @Autowired
     private SysUserMapper sysUserMapper;
 
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private SysActivationCodeLogMapper sysActivationCodeLogMapper;
+
     /**
      * 查询租户信息
      * 
@@ -184,5 +201,135 @@ public class SysTenantServiceImpl implements ISysTenantService
         }
     }
 
+    /**
+     * 生成激活码
+     * @param tenantId
+     * @param tenantExpirationTime
+     * @return
+     */
+    @Override
+    public AjaxResult crateTenantCode(String tenantId,String tenantExpirationTime) throws Exception {
+        //加密器
+        SymmetricCrypto des = new SymmetricCrypto(SymmetricAlgorithm.DES, "sgEsnN6QWq8W7j5H01020304".getBytes());
+        //激活码生成时间
+        LocalDateTime now = LocalDateTime.now();
+        String nowStr = DateUtils.toLocalDateTimeStr(now);
+        //激活码有效时间默认为24小时
+        LocalDateTime offset = LocalDateTimeUtil.offset(now, 1, ChronoUnit.DAYS);
+        String offsetStr = DateUtils.toLocalDateTimeStr(offset);
+        //激活码生成时间+租户id+激活码有效期+激活多长时间
+        String dataStr=nowStr+"_"+tenantId+"_"+offsetStr+"_"+tenantExpirationTime;
+        //加密信息
+        String encryptHex = des.encryptHex(dataStr);
+        //生成激活码操作
+        activationCodeLog("生成激活码");
+        return AjaxResult.success(encryptHex);
+    }
+
+    /**
+     * 激活码激活操作
+     * @param tenantId
+     * @param activationCode
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public AjaxResult activationOperation(String tenantId, String activationCode) throws Exception {
+        String activeCode="active:code:"+activationCode;//魔法值后期抽出来
+        String strCode = stringRedisTemplate.opsForValue().get(activationCode);
+        if(StringUtils.isNotEmpty(strCode)){
+            return AjaxResult.error("当前激活码已经被使用过了不能重复使用");
+        }
+        //激活码生成时间+租户id+激活码有效期+激活多长时间
+        SymmetricCrypto symmetricCrypto = new SymmetricCrypto(SymmetricAlgorithm.DES, "sgEsnN6QWq8W7j5H01020304".getBytes());
+        String decryptStr = symmetricCrypto.decryptStr(activationCode, CharsetUtil.CHARSET_UTF_8);
+        String[] contentString = decryptStr.split("_");
+        //判断激活码是否失效
+        String expirationDateStr=contentString[2];
+        LocalDateTime expirationDate = DateUtils.toLocalDateTime(expirationDateStr,"yyyy-MM-dd HH:mm:ss");
+        long expirationDateSecond = expirationDate.toEpochSecond(ZoneOffset.ofHours(8));
+        long nowSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
+        if(expirationDateSecond-nowSecond<0){
+            return AjaxResult.error("此激活码已经过期,不能在继续使用");
+        }
+        if(!tenantId.equals(contentString[1])){
+            return AjaxResult.error("当前激活码不能在当前租户使用");
+        }
+        //先查询、这个用户有没有被激活过
+        SysTenant sysTenant = sysTenantMapper.selectSysTenantByTenantId(Long.valueOf(tenantId));
+        SysTenant sysTenantOne=new SysTenant();
+        sysTenantOne.setTenantId(Long.valueOf(tenantId));
+        //判断有没有有被激活过、有时间代表激活过
+        if(StringUtils.isNotEmpty(sysTenant.getTenantExpirationTime())){
+            //解密
+            String LastActiveTime = symmetricCrypto.decryptStr(sysTenant.getTenantExpirationTime(), CharsetUtil.CHARSET_UTF_8);
+            LocalDateTime localDateTime = DateUtils.toLocalDateTime(LastActiveTime, "yyyy-MM-dd HH:mm:ss");
+            //当前日期时间戳
+            long  nowTimeSecond =LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
+            //原来的过期时间
+            long  oldTimeSecond = localDateTime.toEpochSecond(ZoneOffset.ofHours(8));
+            //老的过期时间跟当前时间比较 如果小于0证明已经过期好久了
+            if(oldTimeSecond-nowTimeSecond<0){
+                //新续期的时间从当前时间进行续期操作
+                renewalTime(symmetricCrypto, contentString, sysTenantOne);
+            }else {
+                //老的时间快过期了还没过期(旧到期时间+新到期时间(续期操作))
+                LocalDateTime newActiveDateTime = LocalDateTimeUtil.offset(localDateTime, Long.parseLong(contentString[3]), ChronoUnit.DAYS);
+                //加密
+                String newActiveDateTimeStr= symmetricCrypto.encryptHex(DateUtils.toLocalDateTimeStr(newActiveDateTime));
+                //更新到期时间
+                sysTenantOne.setTenantExpirationTime(newActiveDateTimeStr);
+            }
+        }else {
+            //新续期的时间从当前时间进行续期操作
+            renewalTime(symmetricCrypto, contentString, sysTenantOne);
+        }
+        //更新租户的有效时间
+        sysTenantMapper.updateSysTenant(sysTenantOne);
+        //保存验证码操作日志
+        activationCodeLog("使用激活码");
+        //24小时之后就删除了我们保存的验证码信息
+        stringRedisTemplate.opsForValue().set(activeCode,activationCode,24, TimeUnit.HOURS);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 从当前时间往后续期租户时间
+     * @param symmetricCrypto
+     * @param contentString
+     * @param sysTenantOne
+     */
+    private void renewalTime(SymmetricCrypto symmetricCrypto, String[] contentString, SysTenant sysTenantOne) {
+        //当前时间
+        LocalDateTime localDateTime = DateUtils.toLocalDateTime(DateUtils.toLocalDateTimeStr(LocalDateTime.now()), "yyyy-MM-dd HH:mm:ss");
+        //设置到期时间
+        LocalDateTime activeDateTime = LocalDateTimeUtil.offset(localDateTime, Long.parseLong(contentString[3]), ChronoUnit.DAYS);
+        //加密到期时间
+        String newActiveDateTimeStr= symmetricCrypto.encryptHex(DateUtils.toLocalDateTimeStr(activeDateTime));
+        sysTenantOne.setTenantExpirationTime(newActiveDateTimeStr);
+    }
+
+    /**
+     * 保存激活码操作日志
+     * @param msg
+     */
+    private void activationCodeLog(String msg) {
+        //保存生成激活码日志
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        SysActivationCodeLog activationCodeLog=new SysActivationCodeLog();
+        //生成时间
+        activationCodeLog.setGenerationTime(new Date());
+        //ip
+        activationCodeLog.setIpAddress(IpUtils.getIpAddr());
+        //操作人
+        activationCodeLog.setOperator(user.getUserName());
+        //备注
+        activationCodeLog.setNote(msg);
+        //插入操作日志
+        sysActivationCodeLogMapper.insertDataSource(activationCodeLog);
+    }
+
+
+
 
 }

+ 65 - 0
ruoyi-system/src/main/resources/mapper/system/SysActivationCodeLogMapper.xml

@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysActivationCodeLogMapper">
+    <!--自定义结果集封装-->
+    <resultMap type="SysActivationCodeLog" id="SysActivationCodeLogResult">
+        <id     property="logId"         column="log_id"        />
+        <result property="generationTime"          column="generation_time"          />
+        <result property="operator"   column="operator"  />
+        <result property="ipAddress"         column="ip_address"         />
+        <result property="note"  column="note" />
+    </resultMap>
+    <!--sql片段-->
+    <sql id="selectActivationCodeLogVo">
+        select log_id, generation_time, operator, ip_address, note
+        from sys_activation_code_logs
+    </sql>
+
+    <!--增加操作日志-->
+    <insert id="insertDataSource" useGeneratedKeys="true" keyProperty="logId">
+        insert into sys_activation_code_logs(log_id,generation_time,operator,ip_address,note)
+        values (#{logId},#{generationTime},#{operator},#{ipAddress},#{note})
+    </insert>
+
+    <!--查询此操作日志集合-->
+    <select id="selectActivationCodeLogList" resultMap="SysActivationCodeLogResult">
+        <include refid="selectActivationCodeLogVo"/>
+        <where>
+            <if test="ipAddress != null and ipAddress != ''">
+                AND ip_address = #{ipAddress}
+            </if>
+            <if test="operator != null and operator != ''">
+                AND operator like concat('%', #{operator}, '%')
+            </if>
+            <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
+                AND generation_time &gt;= #{params.beginTime}
+            </if>
+            <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
+                AND generation_time &lt;= #{params.endTime}
+            </if>
+        </where>
+        order by log_id desc
+    </select>
+
+    <!--批量删除-->
+    <delete id="deleteActivationCodeLogByIds" parameterType="Long">
+        delete from sys_activation_code_logs where log_id in
+        <foreach collection="array" item="logId" open="(" separator="," close=")">
+            #{logId}
+        </foreach>
+    </delete>
+
+    <!--清空日志-->
+    <update id="cleanActivationCodeLog">
+        truncate table sys_activation_code_logs
+    </update>
+
+    <!--查询激活码操作日志详情-->
+    <select id="selectActivationCodeLogById" resultMap="SysActivationCodeLogResult">
+        <include refid="selectActivationCodeLogVo"/>
+        where oper_id = #{logId}
+    </select>
+
+</mapper>

+ 7 - 3
ruoyi-system/src/main/resources/mapper/system/SysBpmNodeScriptMapper.xml

@@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="scriptFunctionCode"    column="script_function_code"    />
         <result property="scriptType"    column="script_type"    />
         <result property="scriptDescription"    column="script_description"    />
+        <result property="industryType" column="industry_type"/>
         <result property="delFlag"    column="del_flag"    />
         <result property="createBy"    column="create_by"    />
         <result property="createTime"    column="create_time"    />
@@ -20,7 +21,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectSysBpmNodeScriptVo">
-        select id, script_key, script_function_name, script_name, script_function_code, script_type, script_description, del_flag, create_by, create_time, update_by, update_time from sys_bpm_node_script
+        select id, script_key, script_function_name, script_name, script_function_code, script_type, script_description, industry_type, del_flag, create_by, create_time, update_by, update_time from sys_bpm_node_script
     </sql>
 
     <select id="selectSysBpmNodeScriptList" parameterType="SysBpmNodeScript" resultMap="SysBpmNodeScriptResult">
@@ -32,6 +33,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="scriptFunctionCode != null  and scriptFunctionCode != ''"> and script_function_code = #{scriptFunctionCode}</if>
             <if test="scriptType != null "> and script_type = #{scriptType}</if>
             <if test="scriptDescription != null  and scriptDescription != ''"> and script_description = #{scriptDescription}</if>
+            <if test="industryType != null"> and industry_type = #{industryType}</if>
+             order by create_time desc
     </select>
     
     <select id="selectSysBpmNodeScriptById" parameterType="Long" resultMap="SysBpmNodeScriptResult">
@@ -48,10 +51,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="scriptFunctionCode != null">script_function_code,</if>
             <if test="scriptType != null">script_type,</if>
             <if test="scriptDescription != null">script_description,</if>
+            <if test="industryType != null">industry_type,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
-            <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null">update_time,</if>
             del_flag
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -61,6 +63,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="scriptFunctionCode != null">#{scriptFunctionCode},</if>
             <if test="scriptType != null">#{scriptType},</if>
             <if test="scriptDescription != null">#{scriptDescription},</if>
+            <if test="industryType != null">#{industryType},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             '0'
@@ -76,6 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="scriptFunctionCode != null">script_function_code = #{scriptFunctionCode},</if>
             <if test="scriptType != null">script_type = #{scriptType},</if>
             <if test="scriptDescription != null">script_description = #{scriptDescription},</if>
+            <if test="industryType != null">industry_type = #{industryType},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>

+ 3 - 2
ruoyi-system/src/main/resources/mapper/system/SysTenantMapper.xml

@@ -15,11 +15,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="createTime"    column="create_time"    />
         <result property="isDel"    column="is_del"    />
         <result property="datasourceId" column="datasource_id"/>
-
+        <result property="tenantExpirationTime" column="tenant_expiration_time"/>
     </resultMap>
 
     <sql id="selectSysTenantVo">
-        select tenant_id, tenant_name, tenant_code, owner, contact_info, address, create_by, create_time, is_del,datasource_id from sys_tenant where is_del = '0'
+        select tenant_id, tenant_name, tenant_code, owner, contact_info, address, create_by, create_time, is_del,datasource_id,tenant_expiration_time from sys_tenant where is_del = '0'
     </sql>
 
     <select id="selectSysTenantList" parameterType="SysTenant" resultMap="SysTenantResult">
@@ -75,6 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="datasourceId != null">datasource_id = #{datasourceId},</if>
+            <if test="tenantExpirationTime != null">tenant_expiration_time = #{tenantExpirationTime},</if>
         </trim>
         where tenant_id = #{tenantId}
     </update>

+ 3 - 3
ruoyi-ui/.env.development

@@ -11,10 +11,10 @@ VUE_APP_BASE_API = '/dev-api'
 VUE_CLI_BABEL_TRANSPILE_MODULES = true
 
 #数据引擎模块IP
-VUE_APP_BASE_API2 = 'http://192.168.110.76:8099/'
+VUE_APP_BASE_API2 = 'http://192.168.110.59:8099/'
 
 #表单引擎模块IP
-VUE_APP_BASE_API3 = 'http://192.168.110.76:8088/'
+VUE_APP_BASE_API3 = 'http://192.168.110.59:8088/'
 
 #流程引擎模块IP
-VUE_APP_BASE_API4 = 'http://192.168.110.76:8055/'
+VUE_APP_BASE_API4 = 'http://192.168.110.59:8055/'

+ 9 - 0
ruoyi-ui/src/api/bpmprocess/process.js

@@ -101,6 +101,15 @@ export function updateConfiguration(data) {
     baseURL: process.env.VUE_APP_BASE_API4,
   })
 }
+// 查询流程节点详情
+export function getNodeData(processKey) {
+  return request({
+    url: '/system/configuration/selectByProcessByKey/' + processKey,
+    method: 'get',
+    baseURL: process.env.VUE_APP_BASE_API4,
+  })
+}
+
 
 // 查询流程节点脚本列表
 export function listScript(query) {

+ 26 - 0
ruoyi-ui/src/api/monitor/activationcode.js

@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+
+// 查询操作日志列表
+export function list(query) {
+  return request({
+    url: '/monitor/activationlog/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 删除操作日志
+export function delActivationLog(logId) {
+  return request({
+    url: '/monitor/activationlog/' + logId,
+    method: 'delete'
+  })
+}
+
+// 清空操作日志
+export function cleanActivationLog() {
+  return request({
+    url: '/monitor/activationlog/clean',
+    method: 'delete'
+  })
+}

+ 16 - 1
ruoyi-ui/src/api/system/tenant.js

@@ -75,4 +75,19 @@ export function initTenantMenuData(tenantId) {
     url: `/system/tenant/initTenantMenuData/${tenantId}`,
     method: 'get'
   })
-}
+}
+
+// 生成激活码
+export function createTenantCode(data) {
+  return request({
+    url: `/system/tenant/crateTenantCode/${data.tenantCode}/${data.tenantExpirationDate}`,
+    method: 'get',
+  })
+}
+// 激活码激活租户
+export function activationOperation(data) {
+  return request({
+    url: `/system/tenant/activationOperation/${data.tenantId}/${data.tenantExpirationTime}`,
+    method: 'get',
+  })
+}

+ 21 - 3
ruoyi-ui/src/utils/bpmn/formDataValidate.js

@@ -1,13 +1,31 @@
+import { customTranslate } from "@packages/additional-modules/Translate";
+
 export function formDataValidate(obj) {
+  let res = {
+    flag: true
+  };
   let { rootElements } = obj.rootElement
+  // 流程名称不能为空
   if (!rootElements[0].name) {
     return {
       flag: false,
       msg: '流程名称为必填项!'
     }
   }
-
-  return {
-    flag: true,
+  // 校验节点名不能为空
+  try {
+    rootElements[0].flowElements.forEach(item => {
+      console.log(item);
+      if (!item.name) {
+        res.flag = false;
+        res.msg = `${customTranslate(item.$type.split(':')[1])}的节点名不能为空!`
+        console.log(res);
+        throw 'find Error'
+      }
+    })
+  } catch (error) {
+    console.log(error);
   }
+
+  return res
 }

+ 38 - 1
ruoyi-ui/src/views/bpmprocess/index.vue

@@ -51,7 +51,7 @@
         </el-date-picker>
       </el-form-item>
       <!-- <el-form-item label="版本状态" prop="processVersion">
-       
+
         <el-select
           v-model="queryParams.processVersion"
           value-key="value"
@@ -484,6 +484,43 @@ export default {
     },
     /** 重置按钮操作 */
     resetQuery() {
+
+      let endFormData = {
+        // 节点脚本关联表
+        BpmNodeExceptionList: [{
+          id:null,
+          nodeKey: null,           // 节点别名
+          scriptKey: null,         // 脚本别名
+          scriptTriggerType: null  // 脚本触发机制(0:手动 1:自动)
+        }],
+        // 节点操作人 -》 数据传输分两种情况:1.当前节点勾选了指定用户,就需要前端生成一个虚拟的角色编码、以及指定的用户id、真实的角色编码null即可
+        // 2.当前节点根据角色勾选的执行人,就需要存贮真实的角色权限字符 生成一个虚拟的角色编码,其他为null即可
+        // 节点处理人表
+        BpmNodeHandleUser: [{
+          id:null,
+          virtuallyRole: null,  // 前端生成的虚拟角色编码
+          realRole: null,       // 真实的角色编码  [1,2,3]/[1]
+          executeUserNo: null   // 用户编码  [1,2,3]/[1]
+        }],
+        // 所有节点表
+        BpmProcessConfigurationList: [{
+          id:null,
+          nodeKey: null,          // 节点别名
+          nodeName: null,         // 节点名称
+          nodeFormKey: null,      // 节点表单别名
+          nodeProcessKey: null,   // 流程别名
+          nodeType: null,         // 节点类型(判断节点、正常节点。。。)根据字典维护
+          nodeBefor: null,        // 节点前
+          nodeAfter: null,        // 节点后
+          nodeRolePermission: null,// 节点对应的角色权限字符(只存虚拟角色编码)
+          spare1: null,             // 备用列
+          spare2: null,
+          spare3: null,
+          createBy: null,            // 创建者
+          updateBy: null,            // 修改者
+          remark: null              // 节点描述
+        }]
+      }
       this.resetForm("queryForm");
       this.handleQuery();
     },

+ 82 - 24
ruoyi-ui/src/views/bpmprocess/scriptManage.vue

@@ -8,14 +8,14 @@
       v-show="showSearch"
       label-width="68px"
     >
-      <el-form-item label="脚本编码" prop="scriptKey">
+      <!-- <el-form-item label="脚本编码" prop="scriptKey">
         <el-input
           v-model="queryParams.scriptKey"
           placeholder="请输入脚本编码"
           clearable
           @keyup.enter.native="handleQuery"
         />
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item label="脚本方法名称" prop="scriptFunctionName">
         <el-input
           v-model="queryParams.scriptFunctionName"
@@ -32,14 +32,6 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="脚本描述" prop="scriptDescription">
-        <el-input
-          v-model="queryParams.scriptDescription"
-          placeholder="请输入脚本描述"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
       <el-form-item>
         <el-button
           type="primary"
@@ -114,7 +106,7 @@
     >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="脚本编码" align="center" prop="scriptKey" />
+      <!-- <el-table-column label="脚本编码" align="center" prop="scriptKey" /> -->
       <el-table-column
         label="脚本方法名称"
         align="center"
@@ -126,7 +118,16 @@
         align="center"
         prop="scriptFunctionCode"
       />
-      <el-table-column label="脚本类型" align="center" prop="scriptType" />
+      <el-table-column label="脚本类型" align="center" prop="scriptType">
+        <template slot-scope="scope">
+          {{ getDictLabel(scope.row.scriptType, dict.type.bpm_script_type) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="行业类型" align="center" prop="industryType">
+        <template slot-scope="scope">
+          {{ getDictLabel(scope.row.industryType, dict.type.industry_type) }}
+        </template>
+      </el-table-column>
       <el-table-column
         label="脚本描述"
         align="center"
@@ -168,35 +169,64 @@
 
     <!-- 添加或修改流程节点脚本对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="脚本编码" prop="scriptKey">
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <!-- <el-form-item label="脚本编码:" prop="scriptKey">
           <el-input v-model="form.scriptKey" placeholder="请输入脚本编码" />
+        </el-form-item> -->
+        <el-form-item label="脚本名称:" prop="scriptName">
+          <el-input v-model="form.scriptName" placeholder="请输入脚本名称" />
+        </el-form-item>
+        <el-form-item label="脚本类型:" prop="scriptType">
+          <!-- <el-input v-model="form.scriptName" placeholder="请输入脚本名称" /> -->
+          <el-select
+            v-model="form.scriptType"
+            placeholder="请选择脚本类型"
+            filterable
+          >
+            <el-option
+              v-for="item in dict.type.bpm_script_type"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            >
+            </el-option>
+          </el-select>
         </el-form-item>
-        <el-form-item label="脚本方法名称" prop="scriptFunctionName">
+        <el-form-item label="行业类型:" prop="industryType">
+          <el-select
+            v-model="form.industryType"
+            placeholder="请选择行业类型"
+            filterable
+          >
+            <el-option
+              v-for="item in dict.type.industry_type"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="方法名:" prop="scriptFunctionName">
           <el-input
             v-model="form.scriptFunctionName"
             placeholder="请输入脚本方法名称"
           />
         </el-form-item>
-        <el-form-item label="脚本名称" prop="scriptName">
-          <el-input v-model="form.scriptName" placeholder="请输入脚本名称" />
-        </el-form-item>
-        <el-form-item label="脚本方法体" prop="scriptFunctionCode">
+
+        <el-form-item label="方法体:" prop="scriptFunctionCode">
           <el-input
             v-model="form.scriptFunctionCode"
             type="textarea"
             placeholder="请输入内容"
           />
         </el-form-item>
-        <el-form-item label="脚本描述" prop="scriptDescription">
+        <el-form-item label="脚本描述:" prop="scriptDescription">
           <el-input
             v-model="form.scriptDescription"
             placeholder="请输入脚本描述"
           />
         </el-form-item>
-        <el-form-item label="删除标志" prop="delFlag">
-          <el-input v-model="form.delFlag" placeholder="请输入删除标志" />
-        </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -214,9 +244,11 @@ import {
   addScript,
   updateScript,
 } from "@/api/bpmprocess/process";
+import uuid from "@/utils/bpmn/uuid";
 
 export default {
   name: "Script",
+  dicts: ["bpm_script_type", "industry_type"],
   data() {
     return {
       // 遮罩层
@@ -246,12 +278,29 @@ export default {
         scriptName: null,
         scriptFunctionCode: null,
         scriptType: null,
+        industryType: null,
         scriptDescription: null,
       },
       // 表单参数
       form: {},
       // 表单校验
-      rules: {},
+      rules: {
+        scriptName: [
+          { required: true, message: "请输入脚本名称", trigger: "blur" },
+        ],
+        scriptFunctionName: [
+          { required: true, message: "请输入脚本函数名", trigger: "blur" },
+        ],
+        scriptFunctionCode: [
+          { required: true, message: "请输入脚本函数体", trigger: "blur" },
+        ],
+        scriptType: [
+          { required: true, message: "请选择脚本类型", trigger: "change" },
+        ],
+        industryType: [
+          { required: true, message: "请选择脚本类型", trigger: "change" },
+        ],
+      },
     };
   },
   created() {
@@ -281,6 +330,7 @@ export default {
         scriptName: null,
         scriptFunctionCode: null,
         scriptType: null,
+        industryType: null,
         scriptDescription: null,
         delFlag: null,
         createBy: null,
@@ -317,6 +367,7 @@ export default {
       this.reset();
       const id = row.id || this.ids;
       getScript(id).then((response) => {
+        response.data.scriptType = response.data.scriptType.toString();
         this.form = response.data;
         this.open = true;
         this.title = "修改流程节点脚本";
@@ -333,6 +384,7 @@ export default {
               this.getList();
             });
           } else {
+            this.form.scriptKey = uuid();
             addScript(this.form).then((response) => {
               this.$modal.msgSuccess("新增成功");
               this.open = false;
@@ -366,6 +418,12 @@ export default {
         `script_${new Date().getTime()}.xlsx`
       );
     },
+    // 获取字典对应label
+    getDictLabel(value, dictLsit = []) {
+      return dictLsit.find((item) => {
+        return item.value == value;
+      })?.label;
+    },
   },
 };
 </script>

+ 7 - 7
ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementExecuteUser.vue

@@ -84,15 +84,15 @@ export default {
     return {
       userTypeList: [
         {
-          value: 1,
+          value: "1",
           label: "指定处理人",
         },
         {
-          value: 2,
+          value: "2",
           label: "批量处理人",
         },
         {
-          value: 3,
+          value: "3",
           label: "角色处理",
         },
       ],
@@ -130,7 +130,7 @@ export default {
   methods: {
     initFormData() {
       this.exeUserValue = getExecuteUser(getActive()) || "";
-      this.exeUserType = getExecuteUserType(getActive()) || "";
+      this.exeUserType = getExecuteUserType(getActive()) || "1";
       Object.assign(this.queryParams, {
         pageNum: 1,
         pageSize: 10,
@@ -140,8 +140,8 @@ export default {
     updateExeUserType(value) {
       setExecuteUserType(getActive(), value);
       value == 2
-        ? setExecuteUser(getActive(), [])
-        : setExecuteUser(getActive(), "");
+        ? setExecuteUser(getActive(), [], this.$route.query.id ? true : false)
+        : setExecuteUser(getActive(), "", this.$route.query.id ? true : false);
       this.exeUserValueList = [];
       this.exeUserValue = "";
       if (!value) return;
@@ -194,7 +194,7 @@ export default {
       }
     },
     updateExeUserValue(value) {
-      setExecuteUser(getActive(), value);
+      setExecuteUser(getActive(), value, this.$route.query.id ? true : false);
     },
     scrollHandler() {
       if (this.isArriveBoottom) return;

+ 17 - 8
ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementGenerations.vue

@@ -86,12 +86,12 @@
           </el-select>
         </edit-item>
 
-        <edit-item key="executable" label="可执行">
+        <!-- <edit-item key="executable" label="可执行">
           <el-switch
             v-model="elFormData.elementExecutable"
             @change="updateElementExecutable"
           />
-        </edit-item>
+        </edit-item> -->
       </template>
     </el-form>
   </el-collapse-item>
@@ -133,9 +133,10 @@ export default {
         startEventType: "",
         bpmType: "",
         nodeDescription: "",
+        elementExecutable: true,
+        scriptTriggerType: false,
       },
 
-      elementExecutable: true,
       isProcess: false,
       // rules: {
       //   elementId: [
@@ -154,11 +155,11 @@ export default {
           { required: true, message: "请输入流程别名/ID", trigger: "blur" },
         ],
       };
-      if (this.isProcess) {
-        res.elementName = [
-          { required: true, message: "请输入流程名称/名称", trigger: "blur" },
-        ];
-      }
+      // if (this.isProcess) {
+      res.elementName = [
+        { required: true, message: "请输入流程/节点名称", trigger: "blur" },
+      ];
+      // }
       return res;
     },
   },
@@ -227,3 +228,11 @@ export default {
   },
 };
 </script>
+
+<style lang="scss" scoped>
+.execute_type {
+  ::v-deep .edit-item_label {
+    width: 100px !important;
+  }
+}
+</style>

+ 142 - 0
ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementNormalTask.vue

@@ -0,0 +1,142 @@
+<template>
+  <el-collapse-item name="element-normal-task">
+    <template #title>
+      <collapse-title title="执行任务">
+        <lucide-icon name="FileSpreadsheet" />
+      </collapse-title>
+    </template>
+    <div class="element-normal-task">
+      <edit-item label="任务行业" :label-width="100">
+        <el-select
+          v-model="industryType"
+          value-key="value"
+          placeholder="请选择行业类型"
+          filterable
+          @change="updateIndustryType"
+        >
+          <el-option
+            v-for="{ label, value } in dict.type.industry_type"
+            :label="label"
+            :value="value"
+            :key="value"
+          />
+        </el-select>
+      </edit-item>
+      <edit-item label="选择任务" :label-width="100">
+        <!-- <el-input
+          v-model="industryType"
+          maxlength="32"
+          @change="setExternalTaskPriority"
+        /> -->
+        <el-select
+          v-model="normalScriptKey"
+          :disabled="!industryType"
+          value-key="value"
+          placeholder="请选择执行任务"
+          clearable
+          filterable
+          @change="updateScriptKey"
+        >
+          <el-option
+            v-for="{ value, label } in scriptList"
+            :key="value"
+            :label="label"
+            :value="value"
+          >
+          </el-option>
+        </el-select>
+      </edit-item>
+      <edit-item label="触发方式" :label-width="100">
+        <!-- <el-input
+          v-model="industryType"
+          maxlength="32"
+          @change="setExternalTaskPriority"
+        /> -->
+        <el-select
+          v-model="scriptTriggerType"
+          value-key="value"
+          placeholder="请选择触发方式"
+          filterable
+          @change="updateScriptTriggerType"
+        >
+          <el-option
+            v-for="{ value, label } in dict.type.script_trigger_type"
+            :key="value"
+            :label="label"
+            :value="value"
+          >
+          </el-option>
+        </el-select>
+      </edit-item>
+    </div>
+  </el-collapse-item>
+</template>
+
+<script>
+import EventEmitter from "@utils/EventEmitter";
+import {
+  setIndustryType,
+  getIndustryType,
+  setNormalScriptKey,
+  getNormalScriptKey,
+  setNormalScriptTriggerType,
+  getNormalScriptTriggerType,
+} from "@packages/bo-utils/myFieldUtil";
+import { getActive } from "@packages/bpmn-utils/BpmnDesignerUtils";
+import { listScript } from "@/api/bpmprocess/process";
+
+export default {
+  name: "ElementNormalTask",
+  dicts: ["industry_type", "script_trigger_type"],
+  data() {
+    return {
+      scriptList: [],
+      industryType: "",
+      normalScriptKey: "",
+      scriptTriggerType: "0",
+    };
+  },
+
+  mounted() {
+    this.initFormData();
+    EventEmitter.on("element-update", () => {
+      this.initFormData();
+    });
+  },
+  methods: {
+    async initFormData() {
+      this.industryType = getIndustryType(getActive());
+      await this.getScriptList(this.industryType);
+      this.normalScriptKey = getNormalScriptKey(getActive());
+      this.scriptTriggerType = getNormalScriptTriggerType(getActive());
+    },
+    updateIndustryType(value) {
+      setIndustryType(getActive(), value);
+      this.getScriptList(value);
+      this.normalScriptKey = "";
+    },
+    async getScriptList(industryType) {
+      let res = await listScript({
+        isEnablePaging: false,
+        scriptType: 1,
+        industryType,
+      });
+      this.scriptList = res.rows.map((item) => ({
+        value: item.scriptKey,
+        label: item.scriptName,
+      }));
+    },
+    updateScriptKey(value) {
+      setNormalScriptKey(getActive(), value);
+    },
+    updateScriptTriggerType(value) {
+      setNormalScriptTriggerType(getActive(), value);
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+::v-deep .edit-item_label {
+  width: 80px !important;
+}
+</style>

+ 103 - 27
ruoyi-ui/src/views/system/bpmnPro/components/Panel/components/ElementUnusualTasks.vue

@@ -1,24 +1,47 @@
 <template>
   <el-collapse-item name="element-unusual-tasks">
     <template #title>
-      <collapse-title title="异常任务">
+      <collapse-title title="管道节点">
         <lucide-icon name="FileX2" />
       </collapse-title>
       <number-tag :value="listeners.length" margin-left="12px" />
     </template>
+    <el-form label-width="110px" :model="scriptForm">
+      <el-form-item label="脚本执行时机:">
+        <el-switch
+          active-text="节点后"
+          inactive-text="节点前"
+          v-model="scriptForm.scriptTriggerType"
+          @change="updateScriptTriggerType"
+        />
+      </el-form-item>
+    </el-form>
     <div class="element-unusual-tasks">
       <el-table border :data="listeners" style="width: 100%" height="200px">
         <el-table-column label="序号" type="index" width="50" />
         <el-table-column
           label="执行脚本"
-          prop="scriptKey"
+          prop="scriptName"
           show-overflow-tooltip
-        />
+        >
+          <!-- <template slot-scope="scope">
+            {{ getDictLabel(scope.row.scriptType, dict.type.bpm_script_type) }}
+          </template> -->
+        </el-table-column>
         <el-table-column
           label="触发方式"
           prop="scriptTriggerType"
           show-overflow-tooltip
-        />
+        >
+          <template slot-scope="scope">
+            {{
+              getDictLabel(
+                scope.row.scriptTriggerType,
+                dict.type.script_trigger_type
+              )
+            }}
+          </template>
+        </el-table-column>
         <el-table-column label="操作" width="140">
           <template slot-scope="{ row, $index }">
             <el-button type="text" @click="openScriptModel($index, row)"
@@ -37,13 +60,13 @@
         icon="el-icon-plus"
         @click="openScriptModel(-1)"
       >
-        添加执行监听
+        添加执行脚本
       </el-button>
     </div>
 
     <el-dialog
       :visible.sync="modelVisible"
-      title="添加可触发的异常任务"
+      title="添加可触发的脚本任务"
       width="640px"
       append-to-body
       destroy-on-close
@@ -55,26 +78,43 @@
         class="need-filled"
         aria-modal="true"
       >
-        <el-form-item path="scriptKey" label="任务脚本">
-          <el-select v-model="newUnusualTask.scriptKey">
+        <el-form-item prop="industryType" label="行业类型">
+          <el-select
+            v-model="newUnusualTask.industryType"
+            @change="industryTypeChangeHandler"
+          >
             <el-option
-              v-for="{ label, value } in scriptKeyList"
+              v-for="{ label, value } in dict.type.industry_type"
               :label="label"
               :value="value"
               :key="value"
             />
           </el-select>
         </el-form-item>
-        <el-form-item path="scriptTriggerType" label="事件触发类型">
-          <el-select v-model="newUnusualTask.scriptTriggerType">
+        <el-form-item prop="scriptKey" label="任务脚本">
+          <el-select
+            v-model="newUnusualTask.scriptKey"
+            @change="scriptKeyChange"
+            :disabled="!newUnusualTask.industryType"
+          >
             <el-option
-              v-for="{ label, value } in scriptTriggerTypeList"
+              v-for="{ label, value } in scriptKeyList"
               :label="label"
               :value="value"
               :key="value"
             />
           </el-select>
         </el-form-item>
+        <el-form-item prop="scriptTriggerType" label="事件触发机制">
+          <el-select v-model="newUnusualTask.scriptTriggerType">
+            <el-option
+              v-for="item in dict.type.script_trigger_type"
+              :label="item.label"
+              :value="item.value"
+              :key="item.value"
+            />
+          </el-select>
+        </el-form-item>
       </el-form>
       <template #footer>
         <el-button @click="modelVisible = false">取 消</el-button>
@@ -92,40 +132,38 @@ import {
   removeUnusualTask,
   updateUnusualTask,
   getUnusualTaskTableData,
+  getScriptTriggerType,
+  setScriptTriggerType,
 } from "@packages/bo-utils/myFieldUtil";
 import { getScriptType } from "@packages/bo-utils/scriptUtil";
 import EventEmitter from "@utils/EventEmitter";
 import { getActive } from "@packages/bpmn-utils/BpmnDesignerUtils";
+import { listScript } from "@/api/bpmprocess/process";
 
 export default {
   name: "ElementUnusualTasks",
+  dicts: ["script_trigger_type", "bpm_script_type", "industry_type"],
   data() {
     return {
       modelVisible: false,
       listeners: [],
       newUnusualTask: {},
+      scriptForm: {
+        scriptTriggerType: false,
+      },
       formRules: {
         scriptKey: {
           required: true,
           trigger: ["blur", "change"],
-          message: "异常任务不能为空",
+          message: "任务脚本不能为空",
         },
         scriptTriggerType: {
           required: true,
           trigger: ["blur", "change"],
-          message: "任务触发方式不能为空",
+          message: "事件触发机制不能为空",
         },
       },
-      scriptKeyList: [
-        {
-          value: 1,
-          label: "缺货异常",
-        },
-        {
-          value: 2,
-          label: "人员异常",
-        },
-      ],
+      scriptKeyList: [],
       scriptTriggerTypeList: [
         {
           value: 0,
@@ -148,20 +186,22 @@ export default {
       this.modelVisible = false;
       this.newUnusualTask = {
         scriptKey: "",
-        scriptTriggerType: 0,
+        scriptTriggerType: "0",
+        industryType: "0",
+        scriptName: "",
         // event: getDefaultEvent(getActive()),
         // type: "class",
       };
       this._listenersRaw = getUnusualTasks(getActive());
+      this.scriptForm.scriptTriggerType = getScriptTriggerType(getActive());
 
       this.listeners = getUnusualTaskTableData(this._listenersRaw);
-      console.log(this.listeners);
     },
 
     updateScriptType(value) {
       this.newUnusualTask.script = {
         scriptFormat: this.newUnusualTask.script?.scriptFormat,
-        scriptType: value,
+        industryType: value,
       };
     },
     removeScript(index) {
@@ -184,10 +224,46 @@ export default {
     async openScriptModel(index, TaskData) {
       this.activeIndex = index;
       TaskData && (this.newUnusualTask = JSON.parse(JSON.stringify(TaskData)));
+      this.getScriptList(this.newUnusualTask.industryType);
       this.modelVisible = true;
       await this.$nextTick();
       this.$refs.formRef && this.$refs.formRef.clearValidate();
     },
+    // 脚本名改变
+    scriptKeyChange(value) {
+      this.newUnusualTask.scriptName =
+        this.scriptKeyList.filter((item) => item.value == value)[0]?.label ||
+        "未命名脚本";
+    },
+
+    updateScriptTriggerType(value) {
+      setScriptTriggerType(getActive(), value);
+    },
+    // 获取字典对应label
+    getDictLabel(value, dictLsit = []) {
+      return dictLsit.find((item) => {
+        return item.value == value;
+      })?.label;
+    },
+
+    // 行业改变回调
+    industryTypeChangeHandler(value) {
+      this.getScriptList(value);
+      this.newUnusualTask.scriptKey = "";
+    },
+
+    // 获取脚本列表
+    async getScriptList(industryType = "0") {
+      let res = await listScript({
+        isEnablePaging: false,
+        scriptType: "0",
+        industryType,
+      });
+      this.scriptKeyList = res.rows.map((item) => ({
+        value: item.scriptKey,
+        label: item.scriptName,
+      }));
+    },
   },
 };
 </script>

+ 10 - 7
ruoyi-ui/src/views/system/bpmnPro/components/Panel/index.vue

@@ -45,6 +45,7 @@ import ElementExecuteUser from "@packages/Panel/components/ElementExecuteUser";
 import ElementBeforeNode from "@packages/Panel/components/ElementBeforeNode";
 import ElementAfterNode from "@packages/Panel/components/ElementAfterNode";
 import ElementUnusualTasks from "@packages/Panel/components/ElementUnusualTasks";
+import ElementNormalTask from "@packages/Panel/components/ElementNormalTask";
 
 export default {
   name: "BpmnPanel",
@@ -147,23 +148,25 @@ export default {
       // this.renderComponents.push(ElementDocumentations); //附加文档
       // isCanbeConditional(element) &&
       //   this.renderComponents.push(ElementConditional);
-      isJobExecutable(element) &&
-        this.renderComponents.push(ElementJobExecution);
+      // isJobExecutable(element) &&
+      //   this.renderComponents.push(ElementJobExecution);
       // this.renderComponents.push(ElementExtensionProperties); //扩展属性
-      isExecutable(element) &&
-        this.renderComponents.push(ElementExecutionListeners);
+      // isExecutable(element) &&
+      //   this.renderComponents.push(ElementExecutionListeners);
       // isAsynchronous(element) &&
       // this.renderComponents.push(ElementAsyncContinuations);
       isStartInitializable(element) &&
         this.renderComponents.push(ElementStartInitiator);
-      this.renderComponents.push(ElementExtensionField);
+      // this.renderComponents.push(ElementExtensionField);
       // 添加执行表单
       isTaskOrUserTask(element) &&
         this.renderComponents.push(ElementExecuteForm);
+      isTaskOrUserTask(element) &&
+        this.renderComponents.push(ElementNormalTask);
       !isProcess(element) && this.renderComponents.push(ElementUnusualTasks); //可处理异常
       isUserTask(element) && this.renderComponents.push(ElementExecuteUser);
-      !isProcess(element) && this.renderComponents.push(ElementBeforeNode);
-      !isProcess(element) && this.renderComponents.push(ElementAfterNode);
+      // !isProcess(element) && this.renderComponents.push(ElementBeforeNode);
+      // !isProcess(element) && this.renderComponents.push(ElementAfterNode);
     },
   },
 };

+ 19 - 12
ruoyi-ui/src/views/system/bpmnPro/components/Toolbar/tools/Save.vue

@@ -15,7 +15,7 @@ import xml from "highlight.js/lib/languages/xml";
 import { getProcessEngine } from "@packages/bpmn-utils/BpmnDesignerUtils";
 import EventEmitter from "@utils/EventEmitter";
 import { formDataValidate } from "@utils/formDataValidate";
-import { getNodeMsg } from "@packages/bo-utils/getNodeMsg";
+import { getNodeMsg, filterNodeMsg } from "@packages/bo-utils/getNodeMsg";
 
 import moment from "moment";
 export default {
@@ -27,6 +27,10 @@ export default {
     formData: {
       from: "formData",
     },
+    nodeData: {
+      from: "nodeData",
+      default: {},
+    },
   },
   methods: {
     async getProcess(type, name = "diagram") {
@@ -95,14 +99,14 @@ export default {
       }
     },
     async saveHandler() {
-      // let formValidate = await EventEmitter.emit("formValidate");
-      // if (!formValidate) {
-      //   return;
-      // }
+      //校验字段合法性
+      // let validateRes = validateBPMNFields();
       let _this = this;
       let formData = _this.formData() || {}; // 当前流程表单详细数据
       let processJsonObj = await this.getProcessJson(); // xml标签转换json
       let validateRes = formDataValidate(processJsonObj);
+      console.log(validateRes);
+      return;
       if (!validateRes.flag) {
         this.$message.error(validateRes.msg);
         return;
@@ -149,7 +153,7 @@ export default {
         updateProcess(subformData).then((res) => {
           if (res.code == 200) {
             _this.$message.success("修改成功");
-            this.saveNodeMsg(xmlObj);
+            this.updateNodeMsg(xmlObj);
           } else {
             _this.$message.error("修改失败");
           }
@@ -167,10 +171,12 @@ export default {
     },
     async saveNodeMsg(obj) {
       let data = getNodeMsg(obj);
+      // console.dir(obj.getElementsByTagName("bpmn:process")[0].id);
+      // return;
       if (!data.bpmProcessConfigurationList.length) return;
       data.bpmProcessConfigurationList.forEach((item) => {
         item.createBy = this.$store.state.user.name;
-        item.nodeProcessKey = obj.id;
+        item.nodeProcessKey = obj.getElementsByTagName("bpmn:process")[0].id;
         item.createTime = moment().format("YYYY-MM-DD HH:mm:ss");
       });
       try {
@@ -180,15 +186,16 @@ export default {
       }
     },
     async updateNodeMsg(obj) {
-      let data = getNodeMsg(obj.warnings);
-      if (!data.bpmProcessConfigurationList.length) return;
-      data.bpmProcessConfigurationList.forEach((item) => {
+      let data = getNodeMsg(obj);
+      let theData = filterNodeMsg(this.nodeData(), data);
+      if (!theData.bpmProcessConfigurationList.length) return;
+      theData.bpmProcessConfigurationList.forEach((item) => {
         item.updateBy = this.$store.state.user.name;
-        item.nodeProcessKey = obj.id || "";
+        item.nodeProcessKey = obj.getElementsByTagName("bpmn:process")[0].id;
         item.updateTime = moment().format("YYYY-MM-DD HH:mm:ss");
       });
       try {
-        let res = await updateConfiguration(data);
+        let res = await updateConfiguration(theData);
       } catch (error) {
         console.log(error);
       }

+ 57 - 13
ruoyi-ui/src/views/system/bpmnPro/components/bo-utils/getNodeMsg.js

@@ -35,23 +35,23 @@ export function getNodeMsg(xmlObj) {
   // let moddle = getModeler.getModdle();
   // console.log(moddle);
   // return;
+  console.dir(xmlObj);
   let prefix = getProcessEngine();
   let { attributes, childNodes } = xmlObj
     .getElementsByTagName("bpmn:process")[0];
-  let bpmProcessConfigurationList = [], bpmNodeHandleUserList = [], bpmNodeScriptRelevanceList = [], attributeArray = ['nodeKey', 'nodeFormKey', 'nodeProcessKey', 'nodeType', 'nodeBefore', 'nodeAfter', 'nodeRolePremission', 'spare1', 'spare2', 'spare3', 'createBy', 'updateBy', 'remark'];
+  let bpmProcessConfigurationList = [], bpmNodeHandleUserList = [], bpmNodeScriptRelevanceList = [], attributeArray = ['nodeKey', 'nodeFormKey', 'nodeProcessKey', 'nodeType', 'nodeRolePremission', 'spare1', 'spare2', 'spare3', 'createBy', 'updateBy', 'remark'];
   childNodes.forEach((node) => {
-    let uuid = uuidv4();
-    bpmNodeScriptRelevanceList = [...bpmNodeScriptRelevanceList, ...getNodeException(node)];//获取节点脚本数据
-    bpmNodeHandleUserList = [...bpmNodeHandleUserList, ...getBpmNodeHandleUser(node, uuid)]
+    // let uuid = uuidv4();
+
     let nodeObj = {
       nodeKey: '',
       nodeName: '',
       nodeFormKey: '', //节点表单别名
       nodeProcessKey: '', //流程别名
       nodeType: '',   //节点类型(判断节点,正常节点..)根据字典维护
-      nodeBefore: '',
-      nodeAfter: '',
-      nodeRolePremission: uuid, //节点对应的角色权限字符
+      nodeBefore: 'false',
+      nodeAfter: 'false',
+      nodeRolePremission: '', //节点对应的角色权限字符
       spare1: '',
       spare2: '',
       spare3: '',
@@ -59,12 +59,18 @@ export function getNodeMsg(xmlObj) {
       updateBy: '',  //修改者
       remark: '',    //节点描述
     }
+    let nodeExceptionList = getNodeException(node, nodeObj)
+    let bpmNodeHandleUser = getBpmNodeHandleUser(node, nodeObj)
+    bpmNodeScriptRelevanceList = [...bpmNodeScriptRelevanceList, ...nodeExceptionList];//获取节点脚本数据
+    bpmNodeHandleUserList = [...bpmNodeHandleUserList, ...bpmNodeHandleUser]
+    console.dir(node);
     attributeArray.forEach(attr => {
       let tempAttr = prefix + ':' + attr
       nodeObj[attr] = node.attributes[tempAttr]?.nodeValue || ''
     });
     nodeObj.nodeKey = node.id;
     nodeObj.nodeType = node.localName;
+    bpmNodeHandleUser.length && (nodeObj.nodeRolePermission = node.getAttribute(`${prefix}:virtuallyRole`));
     if (nodeObj.nodeType == "sequenceFlow") return;
     bpmProcessConfigurationList.push(nodeObj)
   })
@@ -75,11 +81,17 @@ export function getNodeMsg(xmlObj) {
   };
 }
 
-function getNodeException(node) {
-  // console.dir(node);
+function getNodeException(node, nodeObj) {
+  console.dir(node);
   let prefix = getProcessEngine();
   let res = []
   let { children } = node;
+  if (node.getAttribute(`${prefix}:NormalScriptKey`)) {
+    res.push({
+      scriptKey: node.getAttribute(`${prefix}:NormalScriptKey`),
+      scriptTriggerType: node.getAttribute(`${prefix}:NormalScriptTriggerType`)
+    })
+  }
   if (!children.length) return [];
   children = Array.from(children);//数组化
   let extensionElements = children.find((item) => item.nodeName == `bpmn:extensionElements`
@@ -98,17 +110,24 @@ function getNodeException(node) {
     item.nodeKey = node.id;
   })
   // console.log(res);
+  if (res.length) {
+    if (node.getAttribute(`${prefix}:scriptTriggerType`) == 'false') {
+      nodeObj.nodeBefore = 'true';
+    } else {
+      nodeObj.nodeAfter = 'true'
+    }
+  }
   return res;
 }
 
 
-function getBpmNodeHandleUser(node, uuid) {
+function getBpmNodeHandleUser(node, nodeObj) {
   if (node.localName !== 'userTask') return []
-  if (!node.attributes.length) return []
+  if (!node.attributes.length || !node.getAttribute('camunda:executeUser')) return []
   let res = {}, prefix = getProcessEngine();
+  let uuid = node.getAttribute(`${prefix}:virtuallyRole`)
   res.virtuallyRole = uuid;
-  console.dir(node);
-  console.log(node.getAttribute('camunda:executeUserType'), 'aaaa');
+  // nodeObj.nodeRolePremission = uuid
   let type = node.getAttribute('camunda:executeUserType');
   switch (type) {
     case '1':
@@ -125,4 +144,29 @@ function getBpmNodeHandleUser(node, uuid) {
   }
 
   return [res]
+}
+
+
+export function filterNodeMsg(oldMsg, newMsg) {
+  let keys = ['bpmProcessConfigurationList', 'bpmNodeScriptRelevanceList', 'bpmNodeHandleUserList']
+  newMsg[keys[0]].forEach(item => {
+    let sameNode = oldMsg[keys[0]].find((oldItem) => oldItem.nodeKey == item.nodeKey)
+    if (sameNode) {
+      item.id = sameNode.id;
+    }
+  })
+  newMsg[keys[1]].forEach(item => {
+    let sameNode = oldMsg[keys[1]].find((oldItem) => oldItem.nodeKey == item.nodeKey && oldItem.scriptKey == item.scriptKey)
+    if (sameNode) {
+      item.id = sameNode.id;
+    }
+  })
+  newMsg[keys[2]].forEach(item => {
+    let sameNode = oldMsg[keys[2]].find((oldItem) => oldItem.virtuallyRole == item.virtuallyRole)
+    if (sameNode) {
+      item.id = sameNode.id;
+    }
+  })
+
+  return newMsg;
 }

+ 89 - 7
ruoyi-ui/src/views/system/bpmnPro/components/bo-utils/myFieldUtil.js

@@ -7,7 +7,7 @@ import {
 } from "@packages/bpmn-utils/BpmnExtensionElements";
 import { getBusinessObject, is, isAny } from "bpmn-js/lib/util/ModelUtil";
 import { add as collectionAdd } from "diagram-js/lib/util/Collections";
-
+import { v4 as uuidv4 } from "uuid";
 
 // 版本描述
 export function getNoteValue(element) {
@@ -95,13 +95,18 @@ export function isUserTask(element) {
   return is(element, 'bpmn:UserTask');
 }
 
-export function setExecuteUser(element, value) {
+export function setExecuteUser(element, value, isUpdate) {
   const prefix = getProcessEngine();
   const modeling = getModeler.getModeling();
   const businessObject = getBusinessObject(element);
+  let uuid = uuidv4()
   modeling.updateModdleProperties(element, businessObject, {
     [`${prefix}:executeUser`]: value
   });
+  if (isUpdate) return
+  modeling.updateModdleProperties(element, businessObject, {
+    [`${prefix}:virtuallyRole`]: uuid
+  });
 }
 
 
@@ -185,7 +190,7 @@ export function getAfterNdoe(element) {
 }
 
 
-/* 异常任务 */
+/* 脚本任务 */
 
 export function getUnusualTasksContainer(element) {
   const businessObject = getBusinessObject(element);
@@ -207,8 +212,10 @@ export function getUnusualTaskTableData(moddleList = []) {
   const prefix = getProcessEngine();
   let res = moddleList.map(item => {
     return {
-      scriptKey: item?.$attrs[prefix + ':scriptKey'] || '',
-      scriptTriggerType: item?.$attrs[prefix + ':scriptTriggerType'] || 0
+      scriptKey: item?.$attrs.scriptKey || '',
+      scriptTriggerType: item?.$attrs.scriptTriggerType || '0',
+      scriptName: item?.$attrs.scriptName || '',
+      industryType: item?.$attrs.industryType || '0',
     }
   })
   return res
@@ -217,13 +224,15 @@ export function getUnusualTaskTableData(moddleList = []) {
 function updateTaskProperty(element, listener, props) {
   const modeling = getModeler.getModeling();
   const prefix = getProcessEngine();
-  const { scriptKey, scriptTriggerType } = props;
+  const { scriptKey, scriptTriggerType, scriptName, industryType } = props;
 
   const updateProperty = (key, value) =>
-    modeling.updateModdleProperties(element, listener, { [`${prefix}:${key}`]: value });
+    modeling.updateModdleProperties(element, listener, { [`${key}`]: value });
 
   scriptKey && updateProperty("scriptKey", scriptKey);
   scriptTriggerType && updateProperty("scriptTriggerType", scriptTriggerType);
+  scriptName && updateProperty('scriptName', scriptName);
+  industryType && updateProperty('industryType', industryType);
 }
 // 修改任务
 export function updateUnusualTask(element, props, listener) {
@@ -253,3 +262,76 @@ export function getUnusualTasksType(listener) {
   return "";
 }
 
+
+/* 脚本执行时机 */
+
+export function getScriptTriggerType(element) {
+  const prefix = getProcessEngine();
+  return element.businessObject.get(`${prefix}:scriptTriggerType`);
+}
+
+
+export function setScriptTriggerType(element, value) {
+
+  const modeling = getModeler.getModeling();
+  const prefix = getProcessEngine();
+
+  modeling.updateProperties(element, {
+    [`${prefix}:scriptTriggerType`]: value
+  });
+}
+
+
+
+/* 正常任务 */
+
+export function setIndustryType(element, value) {
+  const prefix = getProcessEngine();
+  const modeling = getModeler.getModeling();
+  const businessObject = getBusinessObject(element);
+  modeling.updateModdleProperties(element, businessObject, {
+    [`${prefix}:IndustryType`]: value
+  });
+}
+
+
+export function getIndustryType(element) {
+  const prefix = getProcessEngine();
+  const businessObject = getBusinessObject(element);
+
+  return businessObject.get(`${prefix}:IndustryType`);
+}
+
+
+export function setNormalScriptKey(element, value) {
+  const prefix = getProcessEngine();
+  const modeling = getModeler.getModeling();
+  const businessObject = getBusinessObject(element);
+  modeling.updateModdleProperties(element, businessObject, {
+    [`${prefix}:NormalScriptKey`]: value
+  });
+}
+
+
+export function getNormalScriptKey(element) {
+  const prefix = getProcessEngine();
+  const businessObject = getBusinessObject(element);
+
+  return businessObject.get(`${prefix}:NormalScriptKey`);
+}
+export function setNormalScriptTriggerType(element, value) {
+  const prefix = getProcessEngine();
+  const modeling = getModeler.getModeling();
+  const businessObject = getBusinessObject(element);
+  modeling.updateModdleProperties(element, businessObject, {
+    [`${prefix}:NormalScriptTriggerType`]: value
+  });
+}
+
+
+export function getNormalScriptTriggerType(element) {
+  const prefix = getProcessEngine();
+  const businessObject = getBusinessObject(element);
+
+  return businessObject.get(`${prefix}:NormalScriptTriggerType`);
+}

+ 7 - 1
ruoyi-ui/src/views/system/bpmnPro/index.vue

@@ -36,7 +36,7 @@ import "@bpmn-io/element-template-chooser/dist/element-template-chooser.css";
 import "bpmn-js-bpmnlint/dist/assets/css/bpmn-js-bpmnlint.css";
 import "bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css";
 
-import { getProcess } from "@/api/bpmprocess/process";
+import { getProcess, getNodeData } from "@/api/bpmprocess/process";
 
 export default {
   name: "App",
@@ -51,6 +51,7 @@ export default {
     return {
       formData: undefined,
       xmlString: undefined,
+      nodeData: undefined,
     };
   },
   computed: {
@@ -59,6 +60,7 @@ export default {
   provide() {
     return {
       formData: () => this.formData,
+      nodeData: () => this.nodeData,
     };
   },
   methods: {
@@ -78,6 +80,10 @@ export default {
         if (this.getModeler) {
           this.getModeler.importXML(this.xmlString);
         }
+        let response = await getNodeData(this.formData.processKey);
+        if (response.code == 200) {
+          this.nodeData = response.data;
+        }
       } else {
       }
     }

+ 274 - 0
ruoyi-ui/src/views/system/tenant/code/index.vue

@@ -0,0 +1,274 @@
+<template>
+  <div class="app-container">
+    <div>
+      <el-form ref="form" :model="activationCode" :rules="rulesActivationCode" label-width="80px">
+        <el-form-item label="租户信息" prop="tenantCode">
+          <el-select v-model="activationCode.tenantCode" placeholder="请选择">
+            <el-option
+              v-for="item in tenantList"
+              :key="item.tenantId"
+              :label="item.tenantName"
+              :value="item.tenantId">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="充值时间" prop="tenantExpirationDate" style="width: 300px">
+          <el-input v-model="activationCode.tenantExpirationDate" placeholder="请输入充值天数"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="crateCode">生成激活码</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+      <!-- 激活码生成成功-->
+      <el-dialog :title="title" :visible.sync="activationCodeForm" width="500px" append-to-body>
+        <span v-html="actCode"></span>
+        <div slot="footer" class="dialog-footer">
+          <el-button type="primary" @click="copyToClipboard">一键复制</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </el-dialog>
+    </div>
+    <div style="margin-top: 30px">
+
+      <!--搜索条件表单-->
+      <el-form
+        :model="queryParams"
+        ref="queryForm"
+        size="small"
+        :inline="true"
+        v-show="showSearch"
+        label-width="68px"
+      >
+        <el-form-item label="登录地址" prop="ipAddress">
+          <el-input
+            v-model="queryParams.ipAddress"
+            placeholder="请输入登录地址"
+            clearable
+            style="width: 240px;"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="操作人员" prop="operator">
+          <el-input
+            v-model="queryParams.operator"
+            placeholder="请输入操作人员"
+            clearable
+            style="width: 240px"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="操作时间">
+          <el-date-picker
+            v-model="dateRange"
+            style="width: 240px"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            :default-time="['00:00:00', '23:59:59']"
+          ></el-date-picker>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button
+            type="primary"
+            icon="el-icon-search"
+            size="mini"
+            @click="handleQuery"
+          >搜索</el-button
+          >
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+          >
+        </el-form-item>
+      </el-form>
+
+      <!--表格-->
+      <el-table
+        ref="tables"
+        v-loading="loading"
+        :data="list"
+        @selection-change="handleSelectionChange"
+        :default-sort="defaultSort"
+        @sort-change="handleSortChange"
+        style="margin-top: 20px"
+      >
+
+        <el-table-column type="selection" width="50" align="center" />
+        <el-table-column label="日志编号" align="center" prop="logId" />
+        <el-table-column label="操作人员" align="center" prop="operator" />
+        <el-table-column
+          label="操作ip地址"
+          align="center"
+          prop="ipAddress"
+          :show-overflow-tooltip="true"
+        />
+        <el-table-column
+          label="操作日期"
+          align="center"
+          prop="generationTime"
+          sortable="custom"
+          :sort-orders="['descending', 'ascending']"
+        >
+          <template slot-scope="scope">
+            <span>{{ parseTime(scope.row.generationTime) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="备注" align="center" prop="note">
+        </el-table-column>
+      </el-table>
+      <!--分页器-->
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getCodeLogList"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  listTenant,
+  createTenantCode
+} from "@/api/system/tenant";
+import {list, delActivationLog, cleanActivationLog} from "@/api/monitor/activationcode";
+
+import Clipboard from 'clipboard';
+
+export default {
+  name: "TenantCode",
+  data() {
+    return {
+        options: [],
+        //表单校验
+        rulesActivationCode: {
+          tenantCode: [
+            { required: true, message: "未选择租户信息", trigger: "blur" },
+          ],
+          tenantExpirationDate: [
+            { required: true, message: "租户到期时间为设置", trigger: "blur" },
+          ],
+        },
+        activationCode: {},
+        //租户信息表格数据
+        tenantList: [],
+        activationCodeForm: false,
+        actCode:"",
+        title:"激活码生成成功",
+        // 遮罩层
+        loading: true,
+        // 选中数组
+        ids: [],
+        // 非多个禁用
+        multiple: true,
+        // 显示搜索条件
+        showSearch: true,
+        // 总条数
+        total: 0,
+        // 表格数据
+        list: [],
+        // 是否显示弹出层
+        open: false,
+        // 日期范围
+        dateRange: [],
+        // 默认排序
+        defaultSort: { prop: "operTime", order: "descending" },
+        // 表单参数
+        form: {},
+        // 查询参数
+        queryParams: {
+          pageNum: 1,
+          pageSize: 10,
+          operator: undefined,
+          ipAddress: undefined
+        },
+    }
+  },
+  computed: {
+
+  },
+  created() {
+    this.getList();
+    this.getCodeLogList();
+  },
+  methods: {
+    //查询租户信息列表
+    getList() {
+      listTenant(this.queryParams).then((response) => {
+        this.tenantList = response.rows;
+      });
+    },
+    //创建激活码
+    crateCode(){
+      createTenantCode(this.activationCode).then((response) => {
+         this.activationCodeForm=true;
+         this.actCode=response.msg;
+      });
+    },
+    //激活码复制操作
+    copyToClipboard() {
+      //创建一个新 Clipboard 实例,将目标元素和复制成功时的回调传递给它
+      const clipboard = new Clipboard('button', {
+        text: () => this.actCode, //在这里替换为你要复制的文本
+      });
+      clipboard.on('success', () => {
+        this.activationCodeForm=false;
+        console.log('');
+        this.$message({showClose: true, message: '文本已成功复制到剪贴板', type: 'success'});
+        clipboard.destroy(); //清除 Clipboard 实例
+      });
+      clipboard.on('error', () => {
+        console.error('复制失败');
+        clipboard.destroy(); //清除 Clipboard 实例
+      });
+      //触发按钮点击事件,开始复制操作
+      clipboard.onClick({
+        action: 'copy',
+      });
+    },
+    //取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    //激活码日志信息
+    getCodeLogList() {
+      this.loading = true;
+      list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.list = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.queryParams.pageNum = 1;
+      this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order);
+    },
+    /** 多选框选中数据 */
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.logId);
+      this.multiple = !selection.length;
+    },
+    /** 排序触发事件 */
+    handleSortChange(column, prop, order) {
+      this.queryParams.orderByColumn = column.prop;
+      this.queryParams.isAsc = column.order;
+      this.getList();
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getCodeLogList();
+    },
+  },
+};
+</script>

+ 69 - 5
ruoyi-ui/src/views/system/tenant/index.vue

@@ -177,6 +177,14 @@
               </el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
+          <el-button
+            size="small"
+            type="warning"
+            icon="el-icon-edit"
+            @click="openTenantExpirationTime(scope.row)"
+            v-hasPermi="['system:tenant:remove']"
+            style="margin-left:5px">激活租户
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -306,6 +314,19 @@
         <el-button @click="cancel1">取 消</el-button>
       </div>
     </el-dialog>
+
+    <!-- 激活租户弹出层-->
+    <el-dialog :title="title" :visible.sync="tenantExpirationTimeOpen" width="500px" append-to-body>
+      <el-form ref="form" :model="tenantExpirationTimeFrom" :rules="rulesTenantExpirationTime" label-width="80px">
+        <el-form-item label="激活租户" prop="tenantExpirationTime" label-width="110px">
+          <el-input v-model="tenantExpirationTimeFrom.tenantExpirationTime" placeholder="请输入激活码" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="activationOperationMethod">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -320,6 +341,7 @@ import {
   selectAllUser,
   createTenant,
   initTenantMenuData,
+  activationOperation
 } from "@/api/system/tenant";
 import { getDataSourceInfo, insertDataSource } from "@/api/system/data";
 import { servicesLoading } from "@/utils/ruoyi";
@@ -419,6 +441,16 @@ export default {
           { required: true, message: "端口号不能为空", trigger: "blur" },
         ],
       },
+      //租户激活码弹窗表单
+      tenantExpirationTimeFrom:{},
+      //租户激活码弹窗标题
+      tenantExpirationTimeOpen:false,
+      //租户激活码规则验证
+      rulesTenantExpirationTime: {
+        tenantExpirationTime: [
+          { required: true, message: "请输入租户激活码", trigger: "blur" },
+        ],
+      },
     };
   },
   computed: {
@@ -451,12 +483,12 @@ export default {
     },
     // 数据库名称校验规则
     databaseNameValidator(rule, value, callback){
-      let regex = /^[a-z][a-z0-9]*$/; 
-      if (regex.test(value)) {  
-        callback(); // 输入内容符合规则  
-      } else {  
+      let regex = /^[a-z][a-z0-9]*$/;
+      if (regex.test(value)) {
+        callback(); // 输入内容符合规则
+      } else {
         callback(new Error("只能包含小写字母和数字,且以小写字母开头"));
-      }  
+      }
     },
     // 数据源类型改变回调
     dataSourceTypeChange(type) {
@@ -702,6 +734,38 @@ export default {
         console.log(res);
       });
     },
+    //重置租户激活码表单
+    restTenantExpirationTime() {
+      this.tenantExpirationTimeFrom = {
+        tenantId: null,
+        tenantExpirationTime: null,
+      };
+      this.resetForm("tenantExpirationTimeFrom");
+    },
+    /**打开激活码弹窗*/
+    openTenantExpirationTime(row) {
+      this.reset();
+      console.log(this)
+      const tenantId = row.tenantId || this.ids;
+      console.log(tenantId)
+      this.tenantExpirationTimeFrom.tenantId= row.tenantId
+      this.tenantExpirationTimeOpen=true;
+      this.title="激活租户";
+    },
+    /**激活租户操作*/
+    activationOperationMethod(){
+      console.log("激活租户");
+      console.log(this.tenantExpirationTimeFrom.tenantExpirationTime);
+      this.$refs["form"].validate((valid) => {
+        console.log(valid)
+        if (valid) {
+          activationOperation(this.tenantExpirationTimeFrom).then((response) => {
+            this.$modal.msgSuccess("激活成功");
+            this.open = false;
+          });
+        }
+      });
+    }
   },
 };
 </script>

+ 14 - 0
ruoyi-ui/src/views/tableMange/index.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="app-container">
     <el-row :gutter="20">
+      <el-col :span="18" :class="{ edit: menudata }">
       <el-col :span="18" :class="{ edit: menudata }">
         <el-card shadow="always" :body-style="{ padding: '20px' }">
           <template #header>
@@ -75,6 +76,18 @@
                   }"
                   v-model="scope.row.fieldDescription"
                 />
+                <input
+                  :class="{
+                    isNullDesc:
+                      scope.row.fieldDescription == '' &&
+                      scope.row.isShow &&
+                      isInputInvalid
+                        ? true
+                        : false,
+                    ipt: true,
+                  }"
+                  v-model="scope.row.fieldDescription"
+                />
 
                 <!-- <el-input v-model="scope.row.fieldDescription" /> -->
                 <!-- </el-form-item> -->
@@ -1856,6 +1869,7 @@ export default {
       if (this.dragTableStatisticList.length == 0) {
         this.$message.warning("请确定统计数据字段");
         return;
+        return;
       }
       console.log("确定统计");
 >>>>>>> 6e9cfa0f11bfcd282d3ae391fde4b25bfa0231bd

+ 31 - 28
ruoyi-ui/src/views/tablelist/commonTable/listInfo.vue

@@ -41,7 +41,7 @@
             :underline="false"
             style="font-size: 12px; vertical-align: baseline"
             @click="importTemplate"
-            >下载模板
+          >下载模板
           </el-link>
         </div>
       </el-upload>
@@ -64,7 +64,7 @@
           icon="el-icon-plus"
           size="mini"
           @click="handleAdd"
-          >新增
+        >新增
         </el-button>
       </el-col>
       <el-col :span="1.5" v-if="false">
@@ -75,7 +75,7 @@
           size="mini"
           :disabled="single"
           @click="handleUpdate"
-          >修改
+        >修改
         </el-button>
       </el-col>
       <el-col :span="1.5">
@@ -86,7 +86,7 @@
           size="mini"
           :disabled="multiple"
           @click="handleDelete"
-          >删除
+        >删除
         </el-button>
       </el-col>
       <el-col :span="1.5">
@@ -95,7 +95,7 @@
           icon="el-icon-upload2"
           size="mini"
           @click="upload.open = true"
-          >导入
+        >导入
         </el-button>
       </el-col>
       <el-col :span="1.5">
@@ -105,7 +105,7 @@
           icon="el-icon-download"
           size="mini"
           @click="handleExport"
-          >导出
+        >导出
         </el-button>
       </el-col>
       <right-toolbar
@@ -154,7 +154,7 @@
                   type="text"
                   icon="el-icon-edit"
                   @click="handleUpdate(scope.row)"
-                  >修改
+                >修改
                 </el-button>
               </el-dropdown-item>
               <el-dropdown-item>
@@ -163,7 +163,7 @@
                   type="text"
                   icon="el-icon-delete"
                   @click="handleDelete(scope.row)"
-                  >删除
+                >删除
                 </el-button>
               </el-dropdown-item>
             </el-dropdown-menu>
@@ -212,14 +212,14 @@ import {
   addTableData,
   batchEdit,
 } from "@/api/tablelist/commonTable";
-import { getToken } from "@/utils/auth";
+import {getToken} from "@/utils/auth";
 import Queryfrom from "@/views/tablelist/commonTable/queryfrom.vue";
-import { camelCase } from "@/utils";
-import { inputDisableComplete } from "@/utils/other";
+import {camelCase} from "@/utils";
+import {inputDisableComplete} from "@/utils/other";
 
 export default {
   name: "listInfo",
-  components: { Queryfrom },
+  components: {Queryfrom},
   data() {
     return {
       // 遮罩层
@@ -258,18 +258,18 @@ export default {
         // 是否更新已经存在的数据
         updateSupport: 0,
         // 设置上传的请求头部
-        headers: { Authorization: "Bearer " + getToken() },
+        headers: {Authorization: "Bearer " + getToken()},
         // 上传的地址
         url: process.env.VUE_APP_BASE_API3 + "common/uploadData",
       },
       // 排序方式 默认降序
-      sortState: true,
+      sortOrder: true,
       // 共通查询参数接受子组件的参数
       queryParams: {
         pageNum: 1, // 第几页
         pageSize: 10, // 每页大小
         orderByColumn: "", // 根据某列排序
-        isAsc: this.sortState ? "DESC" : "ASC", // desc(降序)或 asc(升序)
+        isAsc: "", // desc(降序)或 asc(升序)
         // 基本查询参数
         basicMap: {
           tableName: "drag_form",
@@ -368,13 +368,15 @@ export default {
       // 序列化当前查询参数列表
       queryParams && (this.queryParams.queryMap = queryParams.queryMap);
       // 获取当前表单结构信息
-      dragTableInfo({ queryMap: { sqlkey: this.sqlkey } })
+      dragTableInfo({queryMap: {sqlkey: this.sqlkey}})
         .then((res) => {
           // 得到当前模版信息 --- sql columns queryWhere
           this.templateInfo = res.data.resultMap;
           this.queryParams.orderByColumn =
             res.data.resultMap.querySql.orderByColumn;
-          this.queryParams.isAsc = res.data.resultMap.querySql.sortOrder;
+          this.sortOrder = JSON.parse(res.data.resultMap.querySql.sortOrder);
+          // 根据拖拽时设置当前列表排列顺序
+          this.queryParams.isAsc = this.sortOrder ? "DESC" : "ASC"
           this.tableName = this.templateInfo.template.dtTableName;
           // 得到查询条件
           this.queryFromWhere = res.data.resultMap.where;
@@ -420,9 +422,9 @@ export default {
       this.$refs.mychild.pageList(
         row == undefined
           ? {
-              limit: this.queryParams.pageSize,
-              page: this.queryParams.pageNum,
-            }
+            limit: this.queryParams.pageSize,
+            page: this.queryParams.pageNum,
+          }
           : row
       );
     },
@@ -452,7 +454,7 @@ export default {
     handleAdd(row) {
       // this.reset();
       this.defaultValue = {};
-      getInfoBySqlKey(this.sqlkey).then(({ data }) => {
+      getInfoBySqlKey(this.sqlkey).then(({data}) => {
         if (!data || !data.dfVueTemplate) {
           this.$message.error("当前表格未绑定表单!");
           return;
@@ -469,7 +471,7 @@ export default {
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
-      getInfoBySqlKey(this.sqlkey).then(({ data }) => {
+      getInfoBySqlKey(this.sqlkey).then(({data}) => {
         if (!data || !data.dfVueTemplate) {
           this.$message.error("当前表格未绑定表单!");
           return;
@@ -548,7 +550,8 @@ export default {
           this.$refs.mychild.pageList();
           this.$modal.msgSuccess("删除成功");
         })
-        .catch(() => {});
+        .catch(() => {
+        });
     },
     /** 导出按钮操作 */
     handleExport() {
@@ -581,7 +584,7 @@ export default {
     importTemplate() {
       this.download(
         process.env.VUE_APP_BASE_API3 +
-          `common/exportTemplate?tableName=${this.tableName}&sqlkey=${this.sqlkey}`,
+        `common/exportTemplate?tableName=${this.tableName}&sqlkey=${this.sqlkey}`,
         {},
         `下载模版名称${new Date().getTime()}.xlsx`
       );
@@ -597,10 +600,10 @@ export default {
       this.$refs.upload.clearFiles();
       this.$alert(
         "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
-          response.msg +
-          "</div>",
+        response.msg +
+        "</div>",
         "导入结果",
-        { dangerouslyUseHTMLString: true }
+        {dangerouslyUseHTMLString: true}
       );
       this.$refs.mychild.pageList({
         limit: this.queryParams.pageSize,
@@ -648,7 +651,7 @@ export default {
             updateData.conditionMap[this.templateInfo.template?.primaryKey] =
               this.defaultValue[
                 camelCase(this.templateInfo.template?.primaryKey)
-              ];
+                ];
             Object.keys(values).map((k) => {
               updateData.commMap[k] = values[k];
             });

+ 1 - 1
ruoyi-ui/vue.config.js

@@ -37,7 +37,7 @@ module.exports = {
     proxy: {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
-        target: `http://192.168.110.15:8080`,
+        target: `http://192.168.110.59:8080`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''