自定义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使用,如果指…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
