自定义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使用,如果指…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
