自定义UI对象转流程节点
自定义UI对象转流程节点
- 实体
- 自定义对象转bpmn
activitiy学习 (动态加签,动态流程图,指定节点跳转,指定多人节点跳转)
前端页面仿的这个
提供一个思路
实体
- ActivitiValueVo
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.io.Serializable;
import java.util.Map;@Data
@ApiModel(value = "ActivitiValueVo对象", description = "流程设计主体对象")
public class ActivitiValueVo implements Serializable {private static final long serialVersionUID = -3200115152519475826L;private Integer tableId;/*** 审批名称*/private String workFlowDef;private Integer directorMaxLevel;private String flowPermission;@ApiModelProperty("流程节点")private ChildNodeVo nodeConfig;@ApiModelProperty("发起人提交参数")private Map<String, Object> paramValueMap;@ApiModelProperty(value = "租户id")private Long tenantId;
}
- ChildNodeVo
import cn.morimatsu.phegda.pojo.dto.activiti.ActivitiUserDTO;
import cn.morimatsu.phegda.pojo.vo.common.ActOrderTableFieldVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.io.Serializable;
import java.util.List;
import java.util.Map;@Data
@ApiModel(value = "ChildNodeVo对象", description = "流程节点对象")
public class ChildNodeVo implements Serializable {private static final long serialVersionUID = -5222393104041946672L;/*** 前端展示唯一标识*/@ApiModelProperty("前端展示唯一标识")private String id;/*** 节点Id*/@ApiModelProperty("节点Id")private String nodeId;/*** 节点名称*/@ApiModelProperty("节点名称")private String nodeName;private String error;/*** 类型 : 0,发起人;1,审核人;2,抄送人;3,条件;4,路由;5,条件默认*/@ApiModelProperty("类型 : 0,发起人;1,审核人;2,抄送人;3,条件;4,路由;5,条件默认")private Integer type;@ApiModelProperty("是否禁止编辑: true:禁止编辑")private Boolean disabled;private Integer priorityLevel;/*** 操作类型:1,指定成员;5,发起人;2,部门负责人;*/@ApiModelProperty("操作类型:4,指定成员;5,发起人;2,部门负责人;3:报修人(仅工单验收);")private Integer settype;/*** 部门负责人操作类型:null or 0,自动通过;1,指定审批人*/@ApiModelProperty("部门负责人找不到操作类型:null or 0,自动通过;1,指定审批人")private Integer deptDirectorTaskType;@ApiModelProperty("部门负责人找不到指定审批人")private ActivitiUserDTO deptDirectorTaskUser;private Integer selectMode;private Integer selectRange;private Integer directorLevel;/*** 多人审批时采用的审批方式:0,会签(需所有审批人同意);1,或签(一名审批人同意或拒绝即可)*/@ApiModelProperty("多人审批时采用的审批方式:0,会签(需所有审批人同意);1,或签(一名审批人同意或拒绝即可)")private Integer examineMode;private Integer noHanderAction;private Integer examineEndDirectorLevel;/*** 抄送标志 (弃用)*/@ApiModelProperty("抄送标志 (弃用)")private Integer ccSelfSelectFlag;/*** 条件信息数据*/@ApiModelProperty("条件信息数据")private List<ConditionVo> conditionList;/*** 当前节点操作人员信息*/@ApiModelProperty("当前节点操作人员信息")private List<ActivitiUserDTO> nodeUserList;/*** 下一节点数据 null 为 指向结束节点*/@ApiModelProperty("下一节点数据 null 为 指向结束节点")private ChildNodeVo childNode;/*** type=4时 存放分支数据*/@ApiModelProperty("type=4时 存放分支数据")private List<ChildNodeVo> conditionNodes;/*** type=1时 存放编辑权限字段*/@ApiModelProperty("type=1时 编辑权限字段")private List<ActOrderTableFieldVO> editPermissionsFields;/*** 节点更改数据项 (节点有编辑权限时且也变更了数据时,记录变更字段及数据)*/@ApiModelProperty("节点更改数据项")private List<Map<String, Object>> updateList;/*** 条件为false or true*/@ApiModelProperty("条件为false or true")private Boolean conditionBoo;}
- ConditionVo
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.io.Serializable;
import java.util.List;@Data
@ApiModel(value = "ConditionVo对象", description = "条件信息对象")
public class ConditionVo implements Serializable {private static final long serialVersionUID = -1597728589377233523L;/*** 字段key*/@ApiModelProperty("字段key")private String fieldKey;/*** 字段类型 1:下拉; 2 :区间; 3:单选; 4:时间; 5:选择部门; 6:选择人员; 7 文本; 8 级联; 9 选择供应商; 10 地址; 11 下拉单选;* 12 下拉多选; 13 起止日期; 14 数字; 15 设备分类; 16 员工选择; 17 部门选择; 18 周期; 999,额外挂载部门*/@ApiModelProperty("fieldDataType")private Integer fieldDataType;/*** 字段名称*/@ApiModelProperty("字段名称")private String label;/*** 连接符 1,or;2。and;*/@ApiModelProperty("连接符 1,or;2。and;")private Integer connectors;/*** 文本*/@ApiModelProperty("文本 fieldDataType 1:下拉; 3:单选; 5:选择部门; 6:选择人员; 8 级联; 9 选择供应商; 14 数字; 999,额外挂载部门")private Object text;@ApiModelProperty("文本名称 fieldDataType 4:时间; 7 文本; 10 地址; 11 下拉单选; 13 起止日期; 16 员工选择; 17 部门选择; 18 周期;")private String textName;/*** 数值 最小值*/@ApiModelProperty("数值 最小值 fieldDataType 2 :区间;")private String min;/*** 数值 最大值*/@ApiModelProperty("数值 最大值 fieldDataType 2 :区间;")private String max;/*** 集合值集* { <p/>* "123",<p/>* 123 <p/>* }*/@ApiModelProperty("集合值集 12:下拉多选; 15:设备分类;")private List<Object> list;private Object dataInfo;}
自定义对象转bpmn
/*** 递归 转 bpmnModel* @param childNode 数据节点* @param process process* @param paramMap 流程参数* @param nodeId 路由节点 下游节点id (非路由节点传 null)* @param paramValueMap 启动流程参数 非启动时 null* @param keys 非启动流程时 不能为null 获取全部动态参数*/String recursionToBpmnModel(ChildNodeVo childNode, Process process, Map<String, Object> paramMap, String nodeId, Map<String, Object> paramValueMap, Set<String> keys);@Overridepublic String recursionToBpmnModel(ChildNodeVo childNode, Process process, Map<String, Object> paramMap, String nodeId, Map<String, Object> paramValueMap, Set<String> keys) {//主线 结束 拼接 end节点if ((childNode == null || ObjectUtils.isEmpty(childNode.getType())) && ObjectUtils.isEmpty(nodeId)) {EndEvent endEvent = new EndEvent();endEvent.setId(String.format("end_%s", RandomStringUtils.randomAlphabetic(10)));endEvent.setName("结束");process.addFlowElement(endEvent);return endEvent.getId();} else if (childNode == null || ObjectUtils.isEmpty(childNode.getType())) { //&& routing != null//分支线 结束 回归主线return nodeId;}switch (childNode.getType()) {//发起人节点case 0:StartEvent startEvent = new StartEvent();startEvent.setId(String.format("start_%s", RandomStringUtils.randomAlphabetic(10)));startEvent.setName(childNode.getNodeName());childNode.setNodeId(startEvent.getId());childNode.setConditionBoo(Boolean.TRUE);process.addFlowElement(startEvent);SequenceFlow sequenceFlow = new SequenceFlow();sequenceFlow.setId(String.format("flow_%s", RandomStringUtils.randomAlphabetic(10)));sequenceFlow.setSourceRef(startEvent.getId());sequenceFlow.setTargetRef(this.recursionToBpmnModel(childNode.getChildNode(), process, paramMap, nodeId, paramValueMap, keys));if (childNode.getChildNode() == null || ObjectUtils.isEmpty(childNode.getChildNode().getType()))childNode.setChildNode(null);process.addFlowElement(sequenceFlow);return startEvent.getId();//审核人case 1:UserTask userTask = new UserTask();userTask.setName(childNode.getNodeName());String randomStr = RandomStringUtils.randomAlphabetic(5);//固定格式userTask.setAssignee(String.format("${userId_%s}", randomStr));//报修人节点 允许为空 验证阶段if (ObjectUtils.isEmpty(childNode.getNodeUserList())&& !childNode.getSettype().equals(3)) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_NOT_SET_APPROVE,childNode.getNodeName()));//多人会签final MultiInstanceLoopCharacteristics loopCharacteristics = new MultiInstanceLoopCharacteristics();String str = "userTask"; //userList_是否会签_是否或签//是否会签if (childNode.getExamineMode() == null) {str = String.format("%s_%s", str, 0);} else {str = String.format("%s_%s", str, 1);//固定格式if (Objects.equals(childNode.getExamineMode(), 0)) {//0,会签(需所有审批人同意)loopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances==1}");str = String.format("%s_%s", str, 0);} else {//或签(一名审批人同意或拒绝即可)loopCharacteristics.setCompletionCondition("${nrOfCompletedInstances==1}");str = String.format("%s_%s", str, 1);}}userTask.setId(String.format("%s_%s", str, RandomStringUtils.randomAlphabetic(10)));childNode.setNodeId(userTask.getId());childNode.setConditionBoo(Boolean.TRUE);final String userStr = String.format("userList_%s", randomStr);final List<String> users = childNode.getNodeUserList().stream().map(ActivitiUserDTO::getEmployeeNumber).collect(Collectors.toList());paramMap.put(userStr, users);loopCharacteristics.setInputDataItem(String.format("${%s}", userStr));//固定格式loopCharacteristics.setElementVariable(String.format("userId_%s", randomStr));userTask.setLoopCharacteristics(loopCharacteristics);//部门负责人找不到操作类型:null or 0,自动通过;1,指定审批人if (Objects.equals(childNode.getSettype(), 2)) {final ActivitiListener activitiListener = new ActivitiListener();activitiListener.setEvent("create");activitiListener.setImplementationType("class");activitiListener.setImplementation("cn.morimatsu.phegda.config.activitiListener.MakeDeptDirectorTask");userTask.setTaskListeners(Collections.singletonList(activitiListener));}process.addFlowElement(userTask);sequenceFlow = new SequenceFlow();sequenceFlow.setId(String.format("flow_%s", RandomStringUtils.randomAlphabetic(10)));sequenceFlow.setSourceRef(userTask.getId());sequenceFlow.setTargetRef(this.recursionToBpmnModel(childNode.getChildNode(), process, paramMap, nodeId, paramValueMap, keys));if (childNode.getChildNode() == null || ObjectUtils.isEmpty(childNode.getChildNode().getType()))childNode.setChildNode(null);process.addFlowElement(sequenceFlow);return userTask.getId();//抄送人case 2:userTask = new UserTask();userTask.setId(String.format("carbonCopy_%s", RandomStringUtils.randomAlphabetic(10)));userTask.setName(childNode.getNodeName());childNode.setNodeId(userTask.getId());childNode.setConditionBoo(Boolean.TRUE);randomStr = RandomStringUtils.randomAlphabetic(5);//固定格式userTask.setAssignee(String.format("${copyUserId_%s}", randomStr));if (ObjectUtils.isEmpty(childNode.getNodeUserList())) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_NOT_SET_CC_PERSON,childNode.getNodeName()));//多人会签final MultiInstanceLoopCharacteristics loop = new MultiInstanceLoopCharacteristics();final String copyUser = String.format("carbonCopyUserList_%s", randomStr);final List<String> copyUsers = childNode.getNodeUserList().stream().map(ActivitiUserDTO::getEmployeeNumber).collect(Collectors.toList());paramMap.put(copyUser, copyUsers);loop.setInputDataItem(String.format("${%s}", copyUser));//固定格式 抄送人loop.setElementVariable(String.format("copyUserId_%s", randomStr));loop.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances==1}");userTask.setLoopCharacteristics(loop);//抄送final ActivitiListener activitiListener = new ActivitiListener();activitiListener.setEvent("create");activitiListener.setImplementationType("class");activitiListener.setImplementation("cn.morimatsu.phegda.config.activitiListener.MakeCopyUserTask");userTask.setTaskListeners(Collections.singletonList(activitiListener));process.addFlowElement(userTask);sequenceFlow = new SequenceFlow();sequenceFlow.setId(String.format("flow_%s", RandomStringUtils.randomAlphabetic(10)));sequenceFlow.setSourceRef(userTask.getId());sequenceFlow.setTargetRef(this.recursionToBpmnModel(childNode.getChildNode(), process, paramMap, nodeId, paramValueMap, keys));if (childNode.getChildNode() == null || ObjectUtils.isEmpty(childNode.getChildNode().getType()))childNode.setChildNode(null);process.addFlowElement(sequenceFlow);return userTask.getId();//路由case 4:ExclusiveGateway exclusiveGateway = new ExclusiveGateway();exclusiveGateway.setId(String.format("exclusiveGateway_%s", RandomStringUtils.randomAlphabetic(10)));childNode.setNodeId(exclusiveGateway.getId());childNode.setConditionBoo(Boolean.TRUE);process.addFlowElement(exclusiveGateway);if (ObjectUtils.isEmpty(childNode.getConditionNodes())) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_NOT_SET_CONDITION, childNode.getNodeName()));String nodeKey = this.recursionToBpmnModel(childNode.getChildNode(), process, paramMap, nodeId, paramValueMap, keys);if (childNode.getChildNode() == null || ObjectUtils.isEmpty(childNode.getChildNode().getType()))childNode.setChildNode(null);final long count = childNode.getConditionNodes().stream().filter(item -> Objects.equals(item.getType(), 5)).count();if (count > 1) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_DEFAULT_CONDITION_EXCEED_ONE));final Boolean[] bol = new Boolean[]{false};final SequenceFlow[] flows = new SequenceFlow[1];childNode.getConditionNodes()//分支数据.forEach(item -> {//条件节点类型 为 3 or 5if (!Arrays.asList(3, 5).contains(item.getType())) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_CONDITION_NODE_ERROR));//非默认条件 判断分支if (Objects.equals(item.getType(), 3) && ObjectUtils.isEmpty(item.getConditionList())) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_NOT_SET_CONDITION, item.getNodeName()));if (Objects.equals(item.getType(), 3)) {if (ObjectUtils.isEmpty(item.getConditionList())) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_NOT_SET_CONDITION, item.getNodeName()));long c = item.getConditionList().stream().filter(i -> StringUtils.isBlank(i.getFieldKey())).count();if (c > 0) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_NOT_SET_CONDITION, item.getNodeName()));c = item.getConditionList().stream().filter(i -> {switch (i.getFieldDataType()) {case 12: //12:下拉多选case 15: //15:设备分类if (ObjectUtils.isEmpty(i.getList())) return Boolean.TRUE;else return Boolean.FALSE;case 1: //1:下拉;case 3: //3:单选;case 5: //5:选择部门;case 6: //6:选择人员;case 8: //8,级联case 9: //9:选择供应商case 14: //14:数字case 999: //999,额外挂载部门if (ObjectUtils.isEmpty(i.getText())) return Boolean.TRUE;else return Boolean.FALSE;case 4: //4:时间;case 7: //7 文本;case 10: //10:地址case 11: //11:下拉单选case 13: //13:起止日期case 16: //16:员工选择case 17: //17:部门选择case 18: //18:周期if (StringUtils.isBlank(i.getTextName())) return Boolean.TRUE;else return Boolean.FALSE;case 2: //区间if (ObjectUtils.isEmpty(i.getMin()) || ObjectUtils.isEmpty(i.getMax())) return Boolean.TRUE;else return Boolean.FALSE;default: throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_UNKNOWN_COMPUTE_SYMBOL));}}).count();if (c > 0) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_NOT_SET_CONDITION, item.getNodeName()));}SequenceFlow flow = new SequenceFlow();Boolean symbol = false;//顺序 第一条true后 不判断其他分支if (Objects.equals(item.getType(), 3)) {final List<ConditionVo> list = new ArrayList<>(item.getConditionList());//倒叙 因为前台是按照顺序传入 计算也要 顺序计算 迭代器是倒叙计算的。 所以需要倒叙Collections.reverse(list);//非默认条件分支 做判断处理symbol = getSymbol(0, list, paramValueMap, keys);}flow.setId(String.format("flow_%s", RandomStringUtils.randomAlphabetic(10)));//分支条件结果 true 保存对应的节点id//顺序 第一条true后 不判断其他分支item.setNodeId(flow.getId());if (symbol && !bol[0]) {//是否存在true的条件bol[0] = symbol;item.setConditionBoo(Boolean.TRUE);flow.setConditionExpression(String.format("${%s}", symbol));} else {item.setConditionBoo(Boolean.FALSE);flow.setConditionExpression("${false}");}if (Objects.equals(item.getType(), 5)) item.setNodeId(flow.getId());flow.setSourceRef(exclusiveGateway.getId());flow.setTargetRef(this.recursionToBpmnModel(item.getChildNode(), process, paramMap, nodeKey, paramValueMap, keys));if (item.getChildNode() == null || ObjectUtils.isEmpty(item.getChildNode().getType()))item.setChildNode(null);//排除默认线if (Objects.equals(item.getType(), 5)) {flows[0] = flow;} else {//条件分支有true时 移除 默认分支的nodeIdchildNode.getConditionNodes().stream().filter(i -> Objects.equals(i.getType(), 5)).forEach(i -> i.setConditionBoo(Boolean.FALSE));process.addFlowElement(flow);}});//条件中 没有true条件 讲默认置为true条件if (flows[0] == null) throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_BRANCH_CONDITION_NOT_DEFAULT));if (bol[0] == null || !bol[0]) {flows[0].setConditionExpression("${true}");//将默认的条件boo 改为truechildNode.getConditionNodes().stream().filter(item -> Objects.equals(item.getType(), 5)).forEach(item -> item.setConditionBoo(Boolean.TRUE));} else {//将默认条件对应的 nodeId 置空childNode.getConditionNodes().stream().filter(item -> Objects.equals(item.getType(), 5)).forEach(item -> item.setConditionBoo(Boolean.FALSE));}//连默认线process.addFlowElement(flows[0]);return exclusiveGateway.getId();default:throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_UNKNOWN_LABEL_TYPE));}}@Overridepublic Boolean getSymbol(Integer i, List<ConditionVo> conditionVo, Map<String, Object> paramValueMap, Set<String> keys) {if (paramValueMap == null) {//验证流程时写入参数keys.addAll(conditionVo.stream().map(ConditionVo::getFieldKey).collect(Collectors.toSet()));return Boolean.TRUE;}boolean b;//未传参数 条件当 false 处理if (paramValueMap.containsKey(conditionVo.get(i).getFieldKey())) {switch (conditionVo.get(i).getFieldDataType()) {case 12: //12:下拉多选case 15: //15:设备分类final List<String> list = conditionVo.get(i).getList().stream().filter(ObjectUtils::isNotEmpty).map(Object::toString).collect(Collectors.toList());final List<String> list1 = JSONArray.parseArray(paramValueMap.get(conditionVo.get(i).getFieldKey()).toString(), String.class);//无提交数据 falseif (ObjectUtils.isEmpty(list1)) {b = false;break;}list1.removeAll(list);//条件全包含提交内容 差集为空 不为空则非全包含b = ObjectUtils.isEmpty(list1);break;case 1: //1:下拉;case 3: //3:单选;case 5: //5:选择部门;case 6: //6:选择人员;case 8: //8,级联case 9: //9:选择供应商case 999: //999,额外挂载部门String value = String.valueOf(paramValueMap.get(conditionVo.get(i).getFieldKey()));if (StringUtils.isNotBlank(value)) {b = Objects.equals(value, String.valueOf(conditionVo.get(i).getText()));} else b = false;break;case 14: //14:数字value = String.valueOf(paramValueMap.get(conditionVo.get(i).getFieldKey()));if (StringUtils.isNotBlank(value)) {b = new BigDecimal(value).compareTo(new BigDecimal(String.valueOf(conditionVo.get(i).getText()))) == 0;} else b = false;break;case 4: //4:时间;case 7: //7 文本;case 11: //11:下拉单选case 13: //13:起止日期case 18: //18:周期value = String.valueOf(paramValueMap.get(conditionVo.get(i).getFieldKey()));if (StringUtils.isNotBlank(value)) {b = Objects.equals(value, conditionVo.get(i).getTextName());} else b = false;break;case 16: //16:员工选择Map<String, String> hashMap = JSONObject.<HashMap<String, String>>parseObject(conditionVo.get(i).getTextName(), HashMap.class);value = String.valueOf(hashMap.get("managerId"));if (!paramValueMap.containsKey(conditionVo.get(i).getFieldKey())) {b = false;break;}Map<String, String> hashMap1 = JSONObject.<HashMap<String, String>>parseObject(String.valueOf(paramValueMap.get(conditionVo.get(i).getFieldKey())), HashMap.class);String value1 = String.valueOf(hashMap1.get("managerId"));b = Objects.equals(value, value1);break;case 17: //17:部门选择hashMap = JSONObject.<HashMap<String, String>>parseObject(conditionVo.get(i).getTextName(), HashMap.class);value = String.valueOf(hashMap.get("userDepartmentId"));if (!paramValueMap.containsKey(conditionVo.get(i).getFieldKey())|| ObjectUtils.isEmpty(paramValueMap.get(conditionVo.get(i).getFieldKey()))) {b = false;break;}hashMap1 = JSONObject.<HashMap<String, String>>parseObject(String.valueOf(paramValueMap.get(conditionVo.get(i).getFieldKey())), HashMap.class);value1 = String.valueOf(hashMap1.get("userDepartmentId"));b = Objects.equals(value, value1);break;case 10: //10:地址hashMap = JSONObject.<HashMap<String, String>>parseObject(conditionVo.get(i).getTextName(), HashMap.class);List<String> city = JSONArray.parseArray(String.valueOf(hashMap.get("city")), String.class);if (!paramValueMap.containsKey(conditionVo.get(i).getFieldKey())|| ObjectUtils.isEmpty(paramValueMap.get(conditionVo.get(i).getFieldKey()))) {b = false;break;}hashMap1 = JSONObject.<HashMap<String, String>>parseObject(String.valueOf(paramValueMap.get(conditionVo.get(i).getFieldKey())), HashMap.class);List<String> city1 = JSONArray.parseArray(JSONObject.toJSONString(hashMap1.get("city")), String.class);if (ObjectUtils.isEmpty(city1)) {b = false;break;}city.removeAll(city1);b = city.size() == 0;break;case 2: //区间final BigDecimal decimal = new BigDecimal(paramValueMap.get(conditionVo.get(i).getFieldKey()).toString());final BigDecimal min = new BigDecimal(conditionVo.get(i).getMin());final BigDecimal max = new BigDecimal(conditionVo.get(i).getMax());// 原型 数值 min <= decimal <= maxb = min.compareTo(decimal) <= 0 && max.compareTo(decimal) >= 0;break;default: throw new BusinessException(MessageUtils.message(MessagesConstants.ACT_ORDER_UNKNOWN_COMPUTE_SYMBOL));}} else {b = false;}//最后一条 跳出if (i >= conditionVo.size() - 1) {return b;} else {if (conditionVo.get(i).getConnectors() == null || Objects.equals(conditionVo.get(i).getConnectors(), 1)) {i++;return b || getSymbol(i, conditionVo, paramValueMap, keys);} else {i++;return b && getSymbol(i, conditionVo, paramValueMap, keys);}}}相关文章:
自定义UI对象转流程节点
自定义UI对象转流程节点 实体自定义对象转bpmn activitiy学习 (动态加签,动态流程图,指定节点跳转,指定多人节点跳转) 前端页面仿的这个 提供一个思路 实体 ActivitiValueVo import io.swagger.annotations.ApiModel; import io.swagger.a…...
P1-P5_动手学深度学习-pytorch(李沐版,粗浅的笔记)
目录 预告 1.学习深度学习的关键是动手 2.什么是《动手学深度学习》 3.曾经推出的版本(含github链接) 一、课程安排 1.目标 2.内容 3.上课形式 4.你将学到什么 5.资源 二、深度学习的介绍 1.AI地图 2.深度学习在一些应用上…...
Android Studio修改模拟器AVD Manger目录
Android Studio修改虚拟机AVD Manger目录 1、在AS的设备管理器Device Manager中删除原来创建的所有虚拟机(Android Virtual Device); 2、新建一个自定义的AVD目录,例如:D:\Android\AndroidAVD 3、在高级系统设置中增加…...
STM32--MQ2烟雾传感器
本文主要介绍STM32F103C8T6和烟雾传感器模块的控制算法 简介 烟雾模块选用MQ-2气体传感器,根据传感器的电导率随空气中可燃气体浓度的增加而增大的特性检测空气中可燃气体,然后将电导率的变化转换成对应的电信号 MQ系列烟雾传感分类如下: 该…...
GitHub要求开启2FA,否则不让用了。
背景 其实大概在一个多月前,在 GitHub 网页端以及邮箱里都被提示:要求开启 2FA ,即双因子认证;但是当时由于拖延症和侥幸心理作祟,直接忽略了相关信息,毕竟“又不是不能用”。。 只到今天发现 GitHub 直接…...
Python 编程基础 | 第三章-数据类型 | 3.6、元组
一、元组 Python 的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。 1、创建元组 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可,例如: tup1 (physics, ch…...
2023/10/7 -- ARM
【程序状态寄存器读写指令】 1.指令码以及格式 mrs:读取CPSR寄存器的值 mrs 目标寄存器 CPSR:读取CPSR的数值保存到目标寄存器中msr:修改CPSR寄存器的数值msr CPSR,第一操作数:将第一操作数的数值保存到CPSR寄存器中//修改CPSR寄存器,也就表示程序的状…...
yolov5加关键点回归
文章目录 一、数据1)数据准备2)标注文件说明 二、基于yolov5-face 修改自己的yolov5加关键点回归1、dataloader,py2、augmentations.py3、loss.py4、yolo.py 一、数据 1)数据准备 1、手动创建文件夹: yolov5-face-master/data/widerface/tr…...
untitle
实用的科研图形美化处理教程分享 显微照片排版标记 除了统计图表之外,显微照片也是文章中必不可少的实验结果呈现方式。除了常规实验的各种组织切片照片,在空间转录组文章中显微照片更是常见。显微照片的呈现方式也是有讲究的,比如对照片…...
《论文阅读》监督对抗性对比学习在对话中的情绪识别 ACL2023
《论文阅读》监督对抗性对比学习在对话中的情绪识别 前言摘要相关知识最坏样本干扰监督对比学习生成式对抗网络纳什均衡琴森香农散度范式球模型架构监督对抗性对比学习模型结构图实验结果问题前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文…...
2023-10-07 LeetCode每日一题(股票价格跨度)
2023-10-07每日一题 一、题目编号 901. 股票价格跨度二、题目链接 点击跳转到题目位置 三、题目描述 设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度 。 当日股票价格的 跨度 被定义为股票价格小于或等于今天价格的最大连续日数(…...
聊聊分布式架构04——RPC通信原理
目录 RPC通信的基本原理 RPC结构 手撸简陋版RPC 知识点梳理 1.Socket套接字通信机制 2.通信过程的序列化与反序列化 3.动态代理 4.反射 思维流程梳理 码起来 服务端时序图 服务端—Api与Provider模块 客户端时序图 RPC通信的基本原理 RPC(Remote Proc…...
维吉尼亚密码
维吉尼亚密码属于多表代换密码 其中A<–>0,B<–>1,…,Z<–>25,则每个密钥K相当于一个长度为m的字母串,称为密钥字。维吉尼亚密码一次加密m个明文字母。 示例:设m6,密钥字为…...
ubuntu20.04挂载拓展盘保姆级流程
背景:跑模型玩时,发现机子硬盘太小了,搞个1t固态作为挂载盘。以下为操作全流程记录 1、开始root权限操作 sudo su若进不去,考虑是否给root设置过密码,新系统第一次进入需要设置密码。 进入成功: rooty:…...
顶顶通电话机器人接口对接开源ASR(语音识别)
前景介绍 目前大部分用户使用的都是在线ASR按照分钟或者按次付费,之前开源ASR效果太差不具备商用的条件,随着 阿里达摩院发布了大量开源数据集或者海量工业数据训练的模型,识别效果已经和商用ASR差距非常小,完全具备了很多场景代…...
windows消息机制
windows开发比较简单,首先要理解的就是消息机制。 Windows消息机制是指Windows操作系统中的消息传递机制。在Windows中,应用程序通过消息进行通信和交互。消息是一种轻量级的通信方式,用于在不同的窗口、线程或进程之间传递信息。 在Windows…...
整数划分——DP
用 j j j 个数表示 i i i 的方案数,考虑dp 转移考虑最小值是否为1 无限制 若为1,则转移到 f ( i 1 , j 1 ) f(i1, j1) f(i1,j1)不为1,则全部1,转移到 f ( i j , j ) f(ij, j) f(ij,j) 数之间不能重复 那么相当于每次整…...
Git切换用户常用命令
1、查看 查看用户名 : git config user.name查看密码: git config user.password查看邮箱: git config user.email查看配置信息(包含上面的信息): $ git config --list2、新增、切换 修改用户名 git…...
一般香港服务器带宽选多大够用?(带宽计算方法)
在海外IDC市场份额中,香港服务器依托自身优越的服务器资源条件,在各个行业中发挥的重要作用。但是,不同业务对网络带宽的要求各不相同,弄清楚如何计算带宽需求对于确保业务平稳运行至关重要,最好从一开始就使用正…...
vue中使用ali-oss上传文件到阿里云上
1.使用 npm 安装ali-oss npm install ali-oss --save2.写ali-oss.js // 引入ali-oss let OSS require(ali-oss) let client new OSS({region: oss-cn-xxx, // bucket所在的区域, 默认oss-cn-hangzhousecure: true, // secure: 配合region使用,如果指…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
