基于若依的ruoyi-nbcio流程管理系统仿钉钉流程初步完成转bpmn设计(还有bug,以后再修改)

news2025/1/12 6:20:20

更多ruoyi-nbcio功能请看演示系统

gitee源代码地址

前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio

演示地址:RuoYi-Nbcio后台管理系统

     今天初步完成仿钉钉流程转bpmn设计的工作,当然还有不少bug,以后有需要或者网友也帮忙改进。

1、前端

   前端主要部分如下:

previewJson() {
      const getCmpData = name => this.$refs[name].getData()
      // processDesign 返回的是Promise 因为要做校验
      console.log("publish getCmpData",getCmpData)
      const p3 = getCmpData('processDesign')
      console.log("publish p3",p3)
      Promise.all([p3])
      .then(res => {
        const param = {
          processData: res[0].formData
        }
        this.previewResult = JSON.stringify(param, null, 2);//json格式化
        this.previewType = "json";
        this.previewModelVisible = true;
      })
      .catch(err => {
        err.target && (this.activeStep = err.target)
        err.msg && this.$message.warning(err.msg)
      })
    },
    previewXml() {
      const getCmpData = name => this.$refs[name].getData()
      // processDesign 返回的是Promise 因为要做校验
      console.log("publish getCmpData",getCmpData)
      const p3 = getCmpData('processDesign')
      console.log("publish p3",p3)
      Promise.all([p3])
      .then(res => {
        const param = {
          processData: res[0].formData
        }
        var convert = require('xml-js');
        var json = JSON.stringify(param, null, 2);//json格式化
        // 启动流程并将表单数据加入流程变量
        dingdingToBpmn(json).then(res => {
          console.log("dingdingToBpmn res",res)
          if(res.code == 200) {
            this.previewResult = res.msg;
            this.previewType = "xml";
            this.previewModelVisible = true
          }
        })
      })
      .catch(err => {
        err.target && (this.activeStep = err.target)
        err.msg && this.$message.warning(err.msg)
      })
    },
    previewBpmn() {
      const getCmpData = name => this.$refs[name].getData()
      // processDesign 返回的是Promise 因为要做校验
      console.log("publish getCmpData",getCmpData)
      const p3 = getCmpData('processDesign')
      console.log("publish p3",p3)
      Promise.all([p3])
      .then(res => {
        const param = {
          processData: res[0].formData
        }
        var convert = require('xml-js');
        var json = JSON.stringify(param, null, 2);//json格式化
        // 钉钉流程转为bpmn格式
        dingdingToBpmn(json).then(reponse => {
          console.log("dingdingToBpmn reponse",reponse)
          if(reponse.code == 200) {
            this.processView.title = "Bpmn流程图预览";
            this.processView.xmlData = reponse.msg;
          }
        })
        this.processView.open = true;
      })
      .catch(err => {
        err.target && (this.activeStep = err.target)
        err.msg && this.$message.warning(err.msg)
      })
    },

 2、后端主要部分如下:

@Override
	public R<Void> dingdingToBpmn(String ddjson) {	
		try {

            JSONObject object = JSON.parseObject(ddjson, JSONObject.class);
            //JSONObject workflow = object.getJSONObject("process");
            //ddBpmnModel.addProcess(ddProcess);
            //ddProcess.setName (workflow.getString("name"));
            //ddProcess.setId(workflow.getString("processId"));
            ddProcess = new Process();
            ddBpmnModel = new BpmnModel();
            ddSequenceFlows = Lists.newArrayList();
            ddBpmnModel.addProcess(ddProcess);
            ddProcess.setId("Process_"+UUID.randomUUID());
            ddProcess.setName ("dingding演示流程");
            JSONObject flowNode = object.getJSONObject("processData");
            StartEvent startEvent = createStartEvent(flowNode);
            ddProcess.addFlowElement(startEvent);
            String lastNode = create(startEvent.getId(), flowNode);
            EndEvent endEvent = createEndEvent();
            ddProcess.addFlowElement(endEvent);
            ddProcess.addFlowElement(connect(lastNode, endEvent.getId()));

            new BpmnAutoLayout(ddBpmnModel).execute();
            return R.ok(new String(new BpmnXMLConverter().convertToXML(ddBpmnModel)));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("创建失败: e=" + e.getMessage());
        }
	}
	
	String id(String prefix) {
        return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase();
    }

    ServiceTask serviceTask(String name) {
        ServiceTask serviceTask = new ServiceTask();
        serviceTask.setName(name);
        return serviceTask;
    }

    SequenceFlow connect(String from, String to) {
        SequenceFlow flow = new SequenceFlow();
        flow.setId(id("sequenceFlow"));
        flow.setSourceRef(from);
        flow.setTargetRef(to);
        ddSequenceFlows.add(flow);
        return flow;
    }

    StartEvent createStartEvent(JSONObject flowNode) {
    	String nodeType = flowNode.getString("type");
        StartEvent startEvent = new StartEvent();
        startEvent.setId(id("start"));
        if (Type.INITIATOR_TASK.isEqual(nodeType)) {
        	JSONObject properties = flowNode.getJSONObject("properties");
        	if(StringUtils.isNotEmpty(properties.getString("formKey"))) {
        		startEvent.setFormKey(properties.getString("formKey"));
        	}
        }
        return startEvent;
    }

    EndEvent createEndEvent() {
        EndEvent endEvent = new EndEvent();
        endEvent.setId(id("end"));
        return endEvent;
    }


    String create(String fromId, JSONObject flowNode) throws InvocationTargetException, IllegalAccessException {
        String nodeType = flowNode.getString("type");
       
        if (Type.INITIATOR_TASK.isEqual(nodeType)) {
            flowNode.put("incoming", Collections.singletonList(fromId));
            String id = createUserTask(flowNode,nodeType);

            if(flowNode.containsKey("concurrentNodes")) { //并行网关
                return createConcurrentGatewayBuilder(id, flowNode);   
            }
            
            if(flowNode.containsKey("conditionNodes")) { //排它网关或叫条件网关
                return createExclusiveGatewayBuilder(id, flowNode);
            }    
            
            // 如果当前任务还有后续任务,则遍历创建后续任务
            JSONObject nextNode = flowNode.getJSONObject("childNode");
            if (Objects.nonNull(nextNode)) {
                FlowElement flowElement = ddBpmnModel.getFlowElement(id);
                return create(id, nextNode);
            } else {
                return id;
            }
        } else if (Type.USER_TASK.isEqual(nodeType) || Type.APPROVER_TASK.isEqual(nodeType)) {
        	flowNode.put("incoming", Collections.singletonList(fromId));     
            String id = createUserTask(flowNode,nodeType);
            if(flowNode.containsKey("concurrentNodes")) { //并行网关
                return createConcurrentGatewayBuilder(id, flowNode);   
            }
            
            if(flowNode.containsKey("conditionNodes")) { //排它网关或叫条件网关
                return createExclusiveGatewayBuilder(id, flowNode);
            }  
            
            // 如果当前任务还有后续任务,则遍历创建后续任务
            JSONObject nextNode = flowNode.getJSONObject("childNode");
            if (Objects.nonNull(nextNode)) {
                FlowElement flowElement = ddBpmnModel.getFlowElement(id);
                return create(id, nextNode);          
            } else {
            	return id;  
            }
        } else if (Type.SERVICE_TASK.isEqual(nodeType)) {
            flowNode.put("incoming", Collections.singletonList(fromId));
            String id = createServiceTask(flowNode);

            if(flowNode.containsKey("concurrentNodes")) { //并行网关
                return createConcurrentGatewayBuilder(id, flowNode);   
            }
            
            if(flowNode.containsKey("conditionNodes")) { //排它网关或叫条件网关
                return createExclusiveGatewayBuilder(id, flowNode);
            } 
            
            // 如果当前任务还有后续任务,则遍历创建后续任务
            JSONObject nextNode = flowNode.getJSONObject("childNode");
            if (Objects.nonNull(nextNode)) {
                FlowElement flowElement = ddBpmnModel.getFlowElement(id);
                return create(id, nextNode);
            } else {
                return id;
            }
        }  
        else {
            throw new RuntimeException("未知节点类型: nodeType=" + nodeType);
        }
    }

    String createExclusiveGatewayBuilder(String formId, JSONObject flowNode) throws InvocationTargetException, IllegalAccessException {
        //String name = flowNode.getString("nodeName");
        String exclusiveGatewayId = id("exclusiveGateway");
        ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
        exclusiveGateway.setId(exclusiveGatewayId);
        exclusiveGateway.setName("排它条件网关");
        ddProcess.addFlowElement(exclusiveGateway);
        ddProcess.addFlowElement(connect(formId, exclusiveGatewayId));

        if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) {
            return exclusiveGatewayId;
        }
        List<JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList());
        List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());

        List<JSONObject> conditions = Lists.newCopyOnWriteArrayList();
        for (JSONObject element : flowNodes) {
            JSONObject childNode = element.getJSONObject("childNode");
            JSONObject properties = element.getJSONObject("properties");
            String nodeName = properties.getString("title");
            String expression = properties.getString("conditions");

            if (Objects.isNull(childNode)) {
                incoming.add(exclusiveGatewayId);
                JSONObject condition = new JSONObject();
                condition.fluentPut("nodeName", nodeName)
                        .fluentPut("expression", expression);
                conditions.add(condition);
                continue;
            }
            // 只生成一个任务,同时设置当前任务的条件
            childNode.put("incoming", Collections.singletonList(exclusiveGatewayId));
            String identifier = create(exclusiveGatewayId, childNode);
            List<SequenceFlow> flows = ddSequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef()))
                    .collect(Collectors.toList());
            
            flows.stream().forEach(
                    e -> {
                        if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) {
                            e.setName(nodeName);
                        }
                        // 设置条件表达式
                        if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) {
                            e.setConditionExpression(expression);
                        }
                    }
            );
            if (Objects.nonNull(identifier)) {
                incoming.add(identifier);
            }
        }


        JSONObject childNode = flowNode.getJSONObject("childNode");
        if (Objects.nonNull(childNode)) {
            if (incoming == null || incoming.isEmpty()) {
                return create(exclusiveGatewayId, childNode);
            } else {
                // 所有 service task 连接 end exclusive gateway
                childNode.put("incoming", incoming);
                FlowElement flowElement = ddBpmnModel.getFlowElement(incoming.get(0));
                // 1.0 先进行边连接, 暂存 nextNode
                JSONObject nextNode = childNode.getJSONObject("childNode");
                childNode.put("childNode", null);
                String identifier = create(flowElement.getId(), childNode);
                for (int i = 1; i < incoming.size(); i++) {
                	ddProcess.addFlowElement(connect(incoming.get(i), identifier));
                }

                //  针对 gateway 空任务分支 添加条件表达式
                if (!conditions.isEmpty()) {
                    FlowElement flowElement1 = ddBpmnModel.getFlowElement(identifier);
                    // 获取从 gateway 到目标节点 未设置条件表达式的节点
                    List<SequenceFlow> flows = ddSequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef()))
                            .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId))
                            .collect(Collectors.toList());
                    flows.stream().forEach(sequenceFlow -> {
                        if (!conditions.isEmpty()) {
                            JSONObject condition = conditions.get(0);
                            String nodeName = condition.getString("content");
                            String expression = condition.getString("expression");

                            if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) {
                                sequenceFlow.setName(nodeName);
                            }
                            // 设置条件表达式
                            if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) {
                                sequenceFlow.setConditionExpression(expression);
                            }

                            conditions.remove(0);
                        }
                    });

                }

                // 1.1 边连接完成后,在进行 nextNode 创建
                if (Objects.nonNull(nextNode)) {
                    return create(identifier, nextNode);
                } else {
                    return identifier;
                }
            }
        }
        return exclusiveGatewayId;
    }

    String createConcurrentGatewayBuilder(String fromId, JSONObject flowNode) throws InvocationTargetException, IllegalAccessException {
        //String name = flowNode.getString("nodeName");
        //下面创建并行网关并进行连线
    	ParallelGateway parallelGateway = new ParallelGateway();
        String parallelGatewayId = id("parallelGateway");
        parallelGateway.setId(parallelGatewayId);
        parallelGateway.setName("并行网关");
        ddProcess.addFlowElement(parallelGateway);
        ddProcess.addFlowElement(connect(fromId, parallelGatewayId));

        if (Objects.isNull(flowNode.getJSONArray("concurrentNodes"))
                && Objects.isNull(flowNode.getJSONObject("childNode"))) {
            return parallelGatewayId;
        }

        //获取并行列表数据
        List<JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("concurrentNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList());
        List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
        for (JSONObject element : flowNodes) {
            JSONObject childNode = element.getJSONObject("childNode");
            if (Objects.isNull(childNode)) {//没子节点,就把并行id加入入口队列
                incoming.add(parallelGatewayId);
                continue;
            }
            String identifier = create(parallelGatewayId, childNode);
            if (Objects.nonNull(identifier)) {//否则加入有子节点的用户id
                incoming.add(identifier);
            }
        }

        JSONObject childNode = flowNode.getJSONObject("childNode");
       
        if (Objects.nonNull(childNode)) {
            // 普通结束网关
            if (CollectionUtils.isEmpty(incoming)) {
                return create(parallelGatewayId, childNode);
            } else {
                // 所有 user task 连接 end parallel gateway
                childNode.put("incoming", incoming);
                FlowElement flowElement = ddBpmnModel.getFlowElement(incoming.get(0));
                // 1.0 先进行边连接, 暂存 nextNode
                JSONObject nextNode = childNode.getJSONObject("childNode");
                childNode.put("childNode", null); //不加这个,下面创建子节点会进入递归了
                String identifier = create(incoming.get(0), childNode);
                for (int i = 1; i < incoming.size(); i++) {//其中0之前创建的时候已经连接过了,所以从1开始补另外一条
                    FlowElement flowElementIncoming = ddBpmnModel.getFlowElement(incoming.get(i));
                    ddProcess.addFlowElement(connect(flowElementIncoming.getId(), identifier));
                }
                // 1.1 边连接完成后,在进行 nextNode 创建
                if (Objects.nonNull(nextNode)) {
                    return create(identifier, nextNode);
                } else {
                    return identifier;
                }
            }
        }
        if(incoming.size()>0) {
        	return incoming.get(1);
        }
        else {
        	return parallelGatewayId;   
        }
        
    }

    String createUserTask(JSONObject flowNode, String nodeType) {
        List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);
        // 自动生成id
        String id = id("userTask");
        if (incoming != null && !incoming.isEmpty()) {
        	UserTask userTask = new UserTask();
        	JSONObject properties = flowNode.getJSONObject("properties");
        	userTask.setName(properties.getString("title"));
        	userTask.setId(id);
        	List<ExtensionAttribute> attributes = new  ArrayList<ExtensionAttribute>();
        	if (Type.INITIATOR_TASK.isEqual(nodeType)) {
        		ExtensionAttribute extAttribute =  new ExtensionAttribute();
        		extAttribute.setNamespace(ProcessConstants.NAMASPASE);
        		extAttribute.setName("dataType");
        		extAttribute.setValue("INITIATOR");
        		attributes.add(extAttribute);
        		userTask.addAttribute(extAttribute);
        		userTask.setAssignee("${initiator}");
        	} else if (Type.USER_TASK.isEqual(nodeType) || Type.APPROVER_TASK.isEqual(nodeType)) {
        		JSONArray approvers = properties.getJSONArray("approvers");
        		JSONObject approver = approvers.getJSONObject(0);
        		ExtensionAttribute extDataTypeAttribute =  new ExtensionAttribute();
        		extDataTypeAttribute.setNamespace(ProcessConstants.NAMASPASE);
        		extDataTypeAttribute.setName("dataType");
        		extDataTypeAttribute.setValue("USERS");
        		userTask.addAttribute(extDataTypeAttribute);
        		ExtensionAttribute extTextAttribute =  new ExtensionAttribute();
        		extTextAttribute.setNamespace(ProcessConstants.NAMASPASE);
        		extTextAttribute.setName("text");
        		extTextAttribute.setValue(approver.getString("nickName"));
        		userTask.addAttribute(extTextAttribute);
        		userTask.setFormKey(properties.getString("formKey"));
        		userTask.setAssignee(approver.getString("userName"));
        	}
        	
            ddProcess.addFlowElement(userTask);
            ddProcess.addFlowElement(connect(incoming.get(0), id));
        }
        return id;
    }
    
    String createServiceTask(JSONObject flowNode) {
        List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);
        // 自动生成id
        String id = id("serviceTask");
        if (incoming != null && !incoming.isEmpty()) {
            ServiceTask serviceTask = new ServiceTask();
            serviceTask.setName(flowNode.getString("nodeName"));
            serviceTask.setId(id);
            ddProcess.addFlowElement(serviceTask);
            ddProcess.addFlowElement(connect(incoming.get(0), id));
        }
        return id;
    }

    enum Type {

        /**
         * 并行事件
         */
    	CONCURRENT("concurrent", ParallelGateway.class),

        /**
         * 排他事件
         */
        EXCLUSIVE("exclusive", ExclusiveGateway.class),

        /**
         * 服务任务
         */
        SERVICE_TASK("serviceTask", ServiceTask.class),
        
        /**
         * 发起人任务
         */
        INITIATOR_TASK("start", ServiceTask.class),
        
        /**
         * 审批任务
         */
        APPROVER_TASK("approver", ServiceTask.class),
    	
    	/**
         * 用户任务
         */
        USER_TASK("userTask", UserTask.class);

        private String type;

        private Class<?> typeClass;

        Type(String type, Class<?> typeClass) {
            this.type = type;
            this.typeClass = typeClass;
        }

        public final static Map<String, Class<?>> TYPE_MAP = Maps.newHashMap();

        static {
            for (Type element : Type.values()) {
                TYPE_MAP.put(element.type, element.typeClass);
            }
        }

        public boolean isEqual(String type) {
            return this.type.equals(type);
        }

    }

3、效果图如下:   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1274724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【android开发-01】android中toast的用法介绍

1&#xff0c;android中toast的作用 在Android开发中&#xff0c;Toast是一种用于向用户显示简短消息的轻量级对话框。它通常用于向用户提供一些即时的反馈信息&#xff0c;例如操作结果、提示或警告。 Toast的主要作用如下&#xff1a; 提供反馈&#xff1a;Toast可以在用户…

索尼PMW580视频帧EC碎片重组开启方法

索尼PMW580视频帧EC碎片重组开启方法 索尼PMW-580摄像机生成的MXF文件存在严重的碎片化&#xff0c;目前CHS零壹视频恢复程序MXF版、专业版、高级版已经支持重组结构体正常的碎片&#xff0c;同时也支持对于结构体破坏或者覆盖后仅存在音视频帧EC数据的重组&#xff0c;需要注…

记一次:Python的学习笔记二(Django项目1)

前言&#xff1a;书接上回&#xff0c;认识了Python项目环境&#xff0c;那么开始做一些案例了&#xff0c;笔者是Java出身&#xff0c;接触的也大都是web项目&#xff0c;那么Python的web项目有哪些呢&#xff1f;了解了一下有很多&#xff0c;37个之多&#xff0c;有 Django …

深入探究Photoshop图像修复与润饰技巧

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在Photoshop中&#xff0c;图像修复和润饰是强…

KEIL:error 35: undefined line number 原因

error 35: undefined line number 是什么意思 #首先这个错误提示是仿真时候出现的&#xff0c;非编译出现 error 35: undefined line number 其次&#xff0c;这并不是什么没有编译 原因很简单&#xff0c;是因为之前设置了仿真断点&#xff0c;但是在修改程序之后&#xff0…

Linux:docker的网络通信(7)

1.端口映射 端口映射---端口映射机制将容器内的服务提供给外部网络访问 启动容器时&#xff0c;不指定对应的端口&#xff0c;在容器外无法通过网络访问容器内的服务 可随机或指定映射端口范围 -P ---------大写P&#xff0c;开启随机端口 -p 宿主机端口&#xff1a;容器端口…

力扣283题 移动零 双指针解法

移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出…

html/css中用float实现的盒子案例

运行效果&#xff1a; 代码部分&#xff1a; <!doctype html> <html> <head> <meta charset"utf-8"> <title>无标题文档</title> <style type"text/css">.father{width:300px; height:400px; background:gray;…

数据探索:五款免费数据可视化工具概览

数据可视化是解读和传达数据的重要方式&#xff0c;而现在有许多免费的工具可供选择&#xff0c;让您在探索数据时更轻松、更有趣。以下是五款推荐的免费数据可视化工具&#xff1a; Tableau Public&#xff1a; Tableau Public是一款功能强大的可视化工具&#xff0c;能够创建…

POI和EasyExcel读写Excel 操作

POI和EasyExcel读写Excel 操作 1.POI读写Excel 数据1.1 导入依赖1.2 POI Excel 写 03和07版本方式(小数据量)1.3 大文件写HSSF&#xff08;03版&#xff09;1.4 大文件写XSSF&#xff08;07版&#xff09;1.5 大文件写SXSSF 2.POI Excel读 03和07版本方式2.1 读取数据&#xff…

【ASP.NET CORE】数据迁移 codefirst

已经写好实体类&#xff0c;使用add-migration生成数据迁移语句&#xff0c;注意如果项目中有多个dbcontext需要使用 -context 名称&#xff0c;指定下需要使用的dbcontext add-Migration Address -context mvcsqlcontext运行后会生成两个文件 2. 使用Update-Database语句更…

设计模式详解(二):抽象工厂——Abstract Factory

目录导航 抽象工厂及其作用工厂方法的好处工厂方法的实现关系图实现步骤 工厂方法的适用场景工厂方法举例 抽象工厂及其作用 工厂方法是一种创建型设计模式。所谓创建型设计模式是说针对创建对象方面的设计模式。在面向对象的编程语言里&#xff0c;我们通过对象间的相互协作&…

无需繁琐编程 开启高效数据分析之旅!

不学编程做R统计分析&#xff1a;图形界面R Commander官方手册 R Commander是 R 的图形用户界面&#xff0c;不需要键入命令就可通过熟悉的菜单和对话框来访问 R 统计软件。 R 和 R Commander 均可免费安装于所有常见的操作系统——Windows、Mac OS X 和 Linux/UNIX。 本书作…

【你来了】舞台就是你的:深圳COC社区职言职语第2季劲爆来袭......

​ 职言职语第1季活动回顾 活动总结见&#xff1a;【活动总结】0723-COC深圳社区职言职语第1季活动总结之第1视角_架构师李肯-深圳城市开发者社区 (csdn.net) 活动介绍 &#x1f389;&#x1f465; 欢迎加入职言职语第2季活动&#xff01;与我们一起来探索职场的智慧和灵感&…

双链表创建 插入 删除

双链表的创建 #define NULL 0 #include<stdio.h>typedef struct DNode{ //双链表类型int data;struct DNode *prior,*next; }DNode,*DLinkList;bool InitDLinkList(DLinkList &L){L (DNode*)malloc(sizeof(DNode)); //分配一个头结点if (LNULL)…

L1-010:比较大小

题目描述 本题要求将输入的任意3个整数从小到大输出。 输入格式: 输入在一行中给出3个整数&#xff0c;其间以空格分隔。 输出格式: 在一行中将3个整数从小到大输出&#xff0c;其间以“->”相连。 输入样例: 4 2 8输出样例: 2->4->8 程序代码 #include<stdio.h&…

几个linux指令提升编程效率

history history命令是Linux/Unix系统中的一个常用命令&#xff0c;用于查看当前用户在命令行中执行过的命令历史记录。该命令允许用户查看、搜索、编辑和执行之前执行过的命令&#xff0c;为用户提供了方便、快捷的操作方式。 查看历史命令&#xff1a; history查看最近n条…

【android开发-10】android中四种布局详细介绍

在Android开发中&#xff0c;常见的四种布局分别是&#xff1a;线性布局&#xff08;LinearLayout&#xff09;、相对布局&#xff08;RelativeLayout&#xff09;、帧布局&#xff08;FrameLayout&#xff09;和绝对布局&#xff08;AbsoluteLayout&#xff09;。 注意&#…

【紫光同创PCIE教程】——使用官方驱动在Windows下进行DMA读写操作/PIO读写操作

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 紫光同创官方主推的是在linux系统下开发驱动和上层软件&#xff0c;相应地&#xff0c;官方提供了在linux一个基于GTK2…

户外电力检测设备,如何实现远程数据实时互通?

北京某企业专注于电力设备的局部放电检测与监测技术的研究与实践应用&#xff0c;可提供局部放电开关柜检测、高频局部放电发电机检测、电力设备绝缘检测等方案。 在实际项目实施过程&#xff0c;企业工作人员需要在各地电力设施部署放电监测设备并进行检测。由于经常涉及户外的…