基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持多实例自定义条件的流程流转

news/2024/5/19 0:45:30/文章来源:https://blog.csdn.net/qq_40032778/article/details/133947678

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

gitee源代码地址

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

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

1、前端代码,主要修改下面这个文件,如下:

说明几点:

 1.1 增加界面

  1.2 增加自定义条件的逻辑与保存

<template><div><el-row><h4><b>审批人设置</b></h4><el-radio-group v-model="dataType" @change="changeDataType"><el-radio label="USERS">指定用户</el-radio><el-radio label="ROLES">角色</el-radio><el-radio label="DEPTS">部门</el-radio><el-radio label="INITIATOR">发起人</el-radio><el-radio label="MANAGER">部门经理</el-radio></el-radio-group></el-row><el-row><div v-if="dataType === 'USERS'"><el-tag v-for="userText in selectedUser.text" :key="userText" effect="plain">{{userText}}</el-tag><div class="element-drawer__button"><el-button size="mini" type="primary" icon="el-icon-plus" @click="onSelectUsers()">添加用户</el-button></div></div><div v-if="dataType === 'ROLES'"><el-select v-model="roleIds" multiple size="mini" placeholder="请选择 角色" @change="changeSelectRoles"><el-optionv-for="item in roleOptions":key="item.roleId":label="item.roleName":value="`ROLE${item.roleId}`":disabled="item.status === 1"></el-option></el-select></div><div v-if="dataType === 'DEPTS'"><tree-select:width="320":height="400"size="mini":data="deptTreeData":defaultProps="deptProps"multipleclearablecheckStrictlynodeKey="id":checkedKeys="deptIds"@change="checkedDeptChange"></tree-select></div></el-row><el-row><div v-show="showMultiFlog"><el-divider /><h4><b>多实例审批方式</b></h4><el-row><el-radio-group v-model="multiLoopType" @change="changeMultiLoopType()"><el-row><el-radio label="Null">无</el-radio></el-row><el-row><el-radio label="SequentialMultiInstance">会签(需所有审批人同意)</el-radio></el-row><el-row><el-radio label="ParallelMultiInstance">或签(一名审批人同意即可)</el-radio></el-row><el-row><el-radio label="CustomMultiInstance">自定义会签条件</el-radio></el-row></el-radio-group></el-row><el-row v-if="multiLoopType === 'CustomMultiInstance'"><el-input v-model="CustomCompletionCondition" clearable @change="updateLoopCondition" /></el-row><el-row v-if="multiLoopType !== 'Null'"><el-tooltip content="开启后,实例需按顺序轮流审批" placement="top-start" @click.stop.prevent><i class="header-icon el-icon-info"></i></el-tooltip><span class="custom-label">顺序审批:</span><el-switch v-model="isSequential" @change="changeMultiLoopType()" /></el-row></div></el-row><!-- 候选用户弹窗 --><el-dialog title="候选用户" :visible.sync="userOpen" width="60%" append-to-body><el-row type="flex" :gutter="20"><!--部门数据--><el-col :span="7"><el-card shadow="never" style="height: 100%"><div slot="header"><span>部门列表</span></div><div class="head-container"><el-inputv-model="deptName"placeholder="请输入部门名称"clearablesize="small"prefix-icon="el-icon-search"style="margin-bottom: 20px"/><el-tree:data="deptOptions":props="deptProps":expand-on-click-node="false":filter-node-method="filterNode"ref="tree"default-expand-all@node-click="handleNodeClick"/></div></el-card></el-col><el-col :span="17"><el-table ref="multipleTable" height="600" :data="userTableList" border @selection-change="handleSelectionChange"><el-table-column type="selection" width="50" align="center" /><el-table-column label="用户名" align="center" prop="nickName" /><el-table-column label="部门" align="center" prop="dept.deptName" /></el-table><pagination:total="userTotal":page.sync="queryParams.pageNum":limit.sync="queryParams.pageSize"@pagination="getUserList"/></el-col></el-row><div slot="footer" class="dialog-footer"><el-button type="primary" @click="handleTaskUserComplete">确 定</el-button><el-button @click="userOpen = false">取 消</el-button></div></el-dialog></div></template><script>
import { listUser, deptTreeSelect } from "@/api/system/user";
import { listRole } from "@/api/system/role";
import TreeSelect from "@/components/TreeSelect";const userTaskForm = {dataType: '',assignee: '',candidateUsers: '',candidateGroups: '',text: '',// dueDate: '',// followUpDate: '',// priority: ''
}export default {name: "UserTask",props: {id: String,type: String},components: { TreeSelect },data() {return {loading: false,dataType: 'USERS',selectedUser: {ids: [],text: []},userOpen: false,deptName: undefined,deptOptions: [],deptProps: {children: "children",label: "label"},deptTempOptions: [],userTableList: [],userTotal: 0,selectedUserDate: [],roleOptions: [],roleIds: [],deptTreeData: [],deptIds: [],// 查询参数queryParams: {deptId: undefined},showMultiFlog: false,isSequential: false,multiLoopType: 'Null',CustomCompletionCondition: '${nrOfCompletedInstances/nrOfInstances>=1}',};},watch: {id: {immediate: true,handler() {this.bpmnElement = window.bpmnInstances.bpmnElement;this.$nextTick(() => this.resetTaskForm());}},// 根据名称筛选部门树deptName(val) {this.$refs.tree.filter(val);}},beforeDestroy() {this.bpmnElement = null;},methods: {resetTaskForm() {const bpmnElementObj = this.bpmnElement?.businessObject;if (!bpmnElementObj) {return;}this.clearOptionsData()this.dataType = bpmnElementObj['dataType'];if (this.dataType === 'USERS') {let userIdData = bpmnElementObj['candidateUsers'] || bpmnElementObj['assignee'];let userText = bpmnElementObj['text'] || [];if (userIdData && userIdData.toString().length > 0 && userText && userText.length > 0) {this.selectedUser.ids = userIdData?.toString().split(',');this.selectedUser.text = userText?.split(',');}if (this.selectedUser.ids.length > 1) {this.showMultiFlog = true;}} else if (this.dataType === 'ROLES') {this.getRoleOptions();let roleIdData = bpmnElementObj['candidateGroups'] || [];if (roleIdData && roleIdData.length > 0) {this.roleIds = roleIdData.split(',')}this.showMultiFlog = true;} else if (this.dataType === 'DEPTS') {this.getDeptTreeData();let deptIdData = bpmnElementObj['candidateGroups'] || [];if (deptIdData && deptIdData.length > 0) {this.deptIds = deptIdData.split(',');}this.showMultiFlog = true;}this.getElementLoop(bpmnElementObj);},/*** 清空选项数据*/clearOptionsData() {this.selectedUser.ids = [];this.selectedUser.text = [];this.roleIds = [];this.deptIds = [];},// 完成条件updateLoopCondition(condition) {},/*** 更新节点数据*/updateElementTask() {const taskAttr = Object.create(null);for (let key in userTaskForm) {taskAttr[key] = userTaskForm[key];}window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);},/*** 查询部门下拉树结构*/getDeptOptions() {return new Promise((resolve, reject) => {if (!this.deptOptions || this.deptOptions.length <= 0) {deptTreeSelect().then(response => {this.deptTempOptions = response.data;this.deptOptions = response.data;resolve()})} else {reject()}});},/*** 查询部门下拉树结构(含部门前缀)*/getDeptTreeData() {function refactorTree(data) {return data.map(node => {let treeData = { id: `DEPT${node.id}`, label: node.label, parentId: node.parentId, weight: node.weight };if (node.children && node.children.length > 0) {treeData.children = refactorTree(node.children);}return treeData;});}return new Promise((resolve, reject) => {if (!this.deptTreeData || this.deptTreeData.length <= 0) {this.getDeptOptions().then(() => {this.deptTreeData = refactorTree(this.deptOptions);resolve()}).catch(() => {reject()})} else {resolve()}})},/*** 查询部门下拉树结构*/getRoleOptions() {if (!this.roleOptions || this.roleOptions.length <= 0) {listRole().then(response => this.roleOptions = response.rows);}},/** 查询用户列表 */getUserList() {listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {this.userTableList = response.rows;this.userTotal = response.total;});},// 筛选节点filterNode(value, data) {if (!value) return true;return data.label.indexOf(value) !== -1;},// 节点单击事件handleNodeClick(data) {this.queryParams.deptId = data.id;this.getUserList();},// 关闭标签handleClose(tag) {this.selectedUserDate.splice(this.selectedUserDate.indexOf(tag), 1);this.$refs.multipleTable.toggleRowSelection(tag);},// 多选框选中数据handleSelectionChange(selection) {this.selectedUserDate = selection;},onSelectUsers() {this.selectedUserDate = []this.$refs.multipleTable?.clearSelection();this.getDeptOptions();this.userOpen = true;},handleTaskUserComplete() {if (!this.selectedUserDate || this.selectedUserDate.length <= 0) {this.$modal.msgError('请选择用户');return;}userTaskForm.dataType = 'USERS';this.selectedUser.text = this.selectedUserDate.map(k => k.nickName) || [];if (this.selectedUserDate.length === 1) {let data = this.selectedUserDate[0];userTaskForm.assignee = data.userName;userTaskForm.text = data.nickName;userTaskForm.candidateUsers = null;this.showMultiFlog = false;this.multiLoopType = 'Null';this.changeMultiLoopType();} else {userTaskForm.candidateUsers = this.selectedUserDate.map(k => k.userName).join() || null;userTaskForm.text = this.selectedUserDate.map(k => k.nickName).join() || null;userTaskForm.assignee = null;this.showMultiFlog = true;}this.updateElementTask()this.userOpen = false;},changeSelectRoles(val) {let groups = null;let text = null;if (val && val.length > 0) {userTaskForm.dataType = 'ROLES';groups = val.join() || null;let textArr = this.roleOptions.filter(k => val.indexOf(`ROLE${k.roleId}`) >= 0);text = textArr?.map(k => k.roleName).join() || null;} else {userTaskForm.dataType = null;this.multiLoopType = 'Null';}userTaskForm.candidateGroups = groups;userTaskForm.text = text;this.updateElementTask();this.changeMultiLoopType();},checkedDeptChange(checkedIds) {let groups = null;let text = null;this.deptIds = checkedIds;if (checkedIds && checkedIds.length > 0) {userTaskForm.dataType = 'DEPTS';groups = checkedIds.join() || null;let textArr = []let treeStarkData = JSON.parse(JSON.stringify(this.deptTreeData));checkedIds.forEach(id => {let stark = []stark = stark.concat(treeStarkData);while(stark.length) {let temp = stark.shift();if(temp.children) {stark = temp.children.concat(stark);}if(id === temp.id) {textArr.push(temp);}}})text = textArr?.map(k => k.label).join() || null;} else {userTaskForm.dataType = null;this.multiLoopType = 'Null';}userTaskForm.candidateGroups = groups;userTaskForm.text = text;this.updateElementTask();this.changeMultiLoopType();},changeDataType(val) {if (val === 'ROLES' || val === 'DEPTS' || (val === 'USERS' && this.selectedUser.ids.length > 1)) {this.showMultiFlog = true;} else {this.showMultiFlog = false;}this.multiLoopType = 'Null';this.changeMultiLoopType();// 清空 userTaskForm 所有属性值Object.keys(userTaskForm).forEach(key => userTaskForm[key] = null);userTaskForm.dataType = val;console.log("changeDataType this.selectedUser",this.selectedUser);if (val === 'USERS') {if (this.selectedUser && this.selectedUser.ids && this.selectedUser.ids.length > 0) {if (this.selectedUser.ids.length === 1) {userTaskForm.assignee = this.selectedUser.ids[0];} else {userTaskForm.candidateUsers = this.selectedUser.ids.join()}userTaskForm.text = this.selectedUser.text?.join() || null}} else if (val === 'ROLES') {this.getRoleOptions();if (this.roleIds && this.roleIds.length > 0) {userTaskForm.candidateGroups = this.roleIds.join() || null;let textArr = this.roleOptions.filter(k => this.roleIds.indexOf(`ROLE${k.roleId}`) >= 0);userTaskForm.text = textArr?.map(k => k.roleName).join() || null;}} else if (val === 'DEPTS') {this.getDeptTreeData();if (this.deptIds && this.deptIds.length > 0) {userTaskForm.candidateGroups = this.deptIds.join() || null;let textArr = []let treeStarkData = JSON.parse(JSON.stringify(this.deptTreeData));this.deptIds.forEach(id => {let stark = []stark = stark.concat(treeStarkData);while(stark.length) {let temp = stark.shift();if(temp.children) {stark = temp.children.concat(stark);}if(id === temp.id) {textArr.push(temp);}}})userTaskForm.text = textArr?.map(k => k.label).join() || null;}} else if (val === 'MANAGER') {userTaskForm.assignee = "${DepManagerHandler.getUser(execution)}";userTaskForm.text = "部门经理";} else if (val === 'INITIATOR') {userTaskForm.assignee = "${initiator}";userTaskForm.text = "流程发起人";}this.updateElementTask();},getElementLoop(businessObject) {if (!businessObject.loopCharacteristics) {this.multiLoopType = "Null";return;}this.isSequential = businessObject.loopCharacteristics.isSequential;if (businessObject.loopCharacteristics.completionCondition) {if (businessObject.loopCharacteristics.completionCondition.body === "${nrOfCompletedInstances >= nrOfInstances}") {this.multiLoopType = "SequentialMultiInstance";} else if (businessObject.loopCharacteristics.completionCondition.body === "${nrOfCompletedInstances > 0}") {this.multiLoopType = "ParallelMultiInstance";} else {this.multiLoopType = "CustomMultiInstance";}}},changeMultiLoopType() {// 取消多实例配置if (this.multiLoopType === "Null") {window.bpmnInstances.modeling.updateProperties(this.bpmnElement, { loopCharacteristics: null, assignee: null });return;}this.multiLoopInstance = window.bpmnInstances.moddle.create("bpmn:MultiInstanceLoopCharacteristics", { isSequential: this.isSequential });// 更新多实例配置window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {loopCharacteristics: this.multiLoopInstance,assignee: '${assignee}'});// 完成条件let completionCondition = null;// 会签if (this.multiLoopType === "SequentialMultiInstance") {completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: "${nrOfCompletedInstances >= nrOfInstances}" });}// 或签if (this.multiLoopType === "ParallelMultiInstance") {completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: "${nrOfCompletedInstances > 0}" });}// 自定义会签if (this.multiLoopType === "CustomMultiInstance") {completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: this.CustomCompletionCondition });}// 更新模块属性信息window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {collection: '${multiInstanceHandler.getUserNames(execution)}',elementVariable: 'assignee',completionCondition});},}
};
</script><style scoped lang="scss">
.el-row .el-radio-group {margin-bottom: 15px;.el-radio {line-height: 28px;}
}
.el-tag {margin-bottom: 10px;+ .el-tag {margin-left: 10px;}
}.custom-label {padding-left: 5px;font-weight: 500;font-size: 14px;color: #606266;
}</style>

2、增加一个方法通过多ids来获取userNames,因为现在流程都是通过userName来执行流转

@Overridepublic List<String> selectUserNames(List<Long> userIds) {List<SysUser> listuser =  baseMapper.selectBatchIds(userIds);List<String> userNames = new ArrayList<>();for(SysUser sysuser: listuser) {userNames.add(sysuser.getUserName());}return userNames;}
}

3、多实例处理类修改如下

/*** 多实例处理类** @author nbacheng*/
@AllArgsConstructor
@Component("multiInstanceHandler")
public class MultiInstanceHandler {public Set<String> getUserNames(DelegateExecution execution) {Set<String> candidateUserNames = new LinkedHashSet<>();FlowElement flowElement = execution.getCurrentFlowElement();if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask) {UserTask userTask = (UserTask) flowElement;String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) {// 添加候选用户candidateUserNames.addAll(userTask.getCandidateUsers());} else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) {// 获取组的ID,角色ID集合或部门ID集合List<Long> groups = userTask.getCandidateGroups().stream().map(item -> Long.parseLong(item.substring(4))).collect(Collectors.toList());List<Long> userIds = new ArrayList<>();List<String> userNames = new ArrayList<>();if ("ROLES".equals(dataType)) {// 通过角色id,获取所有用户id集合LambdaQueryWrapper<SysUserRole> lqw = Wrappers.lambdaQuery(SysUserRole.class).select(SysUserRole::getUserId).in(SysUserRole::getRoleId, groups);userIds = SimpleQuery.list(lqw, SysUserRole::getUserId);} else if ("DEPTS".equals(dataType)) {// 通过部门id,获取所有用户id集合LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId).in(SysUser::getDeptId, groups);userIds = SimpleQuery.list(lqw, SysUser::getUserId);}// 添加候选用户ISysUserService sysUserService = SpringContextUtils.getBean(ISysUserService.class);userNames = sysUserService.selectUserNames(userIds);userNames.forEach(userName -> candidateUserNames.add(userName));}}return candidateUserNames;}
}

4、效果图如下:

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python Opencv实践 - 车辆统计(2)检测线绘制,车辆数量计数和显示

针对我所使用的视频&#xff0c;对上一节的代码进行了修改&#xff0c;增加了更多参数。 Python Opencv实践 - 车辆统计&#xff08;1&#xff09;读取视频&#xff0c;移除背景&#xff0c;做预处理_亦枫Leonlew的博客-CSDN博客示例中的图像的腐蚀、膨胀和闭运算等需要根据具…

微机原理与接口技术-第七章输入输出接口

文章目录 I/O接口概述I/O接口的典型结构基本功能 I/O端口的编址独立编址统一编址 输入输出指令I/O寻址方式I/O数据传输量I/O保护 16位DOS应用程序DOS平台的源程序框架DOS功能调用 无条件传送和查询传送无条件传送三态缓冲器锁存器接口电路 查询传送查询输入端口查询输出端口 中…

err -110 while initial SD card failed enmmm否系解决方案

1.情况表述 之前把 sd卡从小容量换成了大容量 且运行正常 过了一两个月 发现启动失败 报错&#xff1a;mmc0: error -110 whilst initialising SD card 给出报错图片 2.相关解决方案 给出链接 讲的很有道理&#xff0c;但是 我在bash中没有找到对应内核的驱动文件 SD卡…

【JavaScript】JavaScript基础详解(文末送书)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Java 线程池调度周期性任务“异常“探究

背景 在做性能监控需求的过程中&#xff0c;会存在很多监控任务需要定时执行。比如在卡顿监控的实现中&#xff0c;我们需要每50ms 执行一次主线程调用栈的任务&#xff0c;此时由于任务本身可能存在一些耗时&#xff0c;可能需要对任务下次调度的时间做一些调整&#xff0c;避…

有没有人声和背景音乐分离的神器?

做视频剪辑&#xff0c;二次创作的朋友&#xff0c;需要去除视频中的背景音乐&#xff0c;保留人声&#xff1b;或者去除人声&#xff0c;保留背景音乐。随着用户需求的增多&#xff0c;科技的发展&#xff0c;让我们能通过智能的人声分离软件来实现&#xff0c;下面就来看看如…

XPS的锂电池表征技巧-科学指南针

XPS作为一种表面表征手段&#xff0c;这是它一个很大的限制&#xff0c;同时也是它一个很大的优势&#xff0c;正所谓“其术专则其艺必精”。限于笔者专业背景&#xff0c;此次主要讲述XPS在锂离子电池中的应用。 而由于XPS测试是一种表面分析手段&#xff0c;故其在锂离子电池…

Qt中QFile、QByteArray QDataStream和QTextStream区别及示例

在Qt中&#xff0c;QFile、QByteArray、QDataStream和QTextStream是常用的文件和数据处理类。 主要功能和区别 QFile&#xff1a; QFile是用于读写文本和二进制文件以及资源的I/O设备。可以单独使用QFile&#xff0c;或者更方便地与QTextStream或QDataStream一起使用。 通常在…

最新2023版完美可用的聚合支付系统源码,全开源无后门,适合二开

最新2023版完美可用的聚合易支付系统源码&#xff0c;全开源无后门&#xff0c;真正安全可用。 更新日志&#xff1a; 1.新增微信公众号消息提醒功能 2.重构转账付款功能&#xff0c;支持通过插件扩展 3.商户后台新增代付功能 4.后台新增付款记录列表 5.支付宝插件新增预…

嵌入式养成计划-46----QT--简易版网络聊天室实现--QT如何连接数据库

一百一十九、简易版网络聊天室实现 119.1 QT实现连接TCP协议 119.1.1 基于TCP的通信流程 119.1.2 QT中实现服务器过程 使用QTcpServer实例化一个服务器对象设置监听状态&#xff0c;通过listen()函数&#xff0c;可以监听特定的主机&#xff0c;也可以监听所有客户端&#x…

C++23:多维视图(std::mdspan)

C23&#xff1a;多维视图&#xff08;std::mdspan&#xff09; 介绍 在 C23 中&#xff0c;std::mdspan 是一个非拥有的多维视图&#xff0c;用于表示连续对象序列。这个连续对象序列可以是一个简单的 C 数组、带有大小的指针、std::array、std::vector 或 std::string。 这…

外汇天眼:如何快速玩转外汇市场?这个技巧你必须知道!

在外汇市场中&#xff0c;决定交易成功与否的关键在于投资者的技能和知识扎不扎实&#xff0c;这对投资者获取利润至关重要。然而对于投资者来说&#xff0c;外汇交易市场又是一个复杂且多变的市场&#xff0c;要在外汇市场中获得成功并不容易&#xff0c;需要深入地了解、不断…

部署Vue项目到githubPage中

上传Vue项目到githubPage 例如: 看我发布的地址 前提条件 1. github上有一个仓库并且仓库下有两个分支(main 和 gh-pages) 1.1 main分支保存你的vue项目源码(react或者其他框架的都行) 1.2 gh-pages分支保存的是你项目打包之后的代码(如Vue项目打包完之后是个dist包,…

【Javascrpt】比较,逻辑运算符

目录 比较运算符 逻辑运算符 &&(与&#xff09; ||&#xff08;或&#xff09; 两真&#xff08;||左侧为真&#xff0c;||右侧为真&#xff09; 两假&#xff08;||左侧为假&#xff0c;右侧为假&#xff09; 一真一假&#xff08;||一侧为假&#xff0c;另一侧为…

数据集的特征提取

1、 特征提取 1.1、 将任意数据&#xff08;如文本或图像&#xff09;转换为可用于机器学习的数字特征 注&#xff1a;特征值化是为了计算机更好的去理解数据 字典特征提取(特征离散化)文本特征提取图像特征提取&#xff08;深度学习将介绍&#xff09; 2 特征提取API sklear…

物联网AI MicroPython传感器学习 之 GC7219点阵屏驱动模块

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 LED-8 * 32点阵屏显示板由 4 块单色 8x8 共阴红色点阵单元组成&#xff0c;通过 SPI 菊花链模式将多块显示屏连接后可以组成更大的分辨率显示屏幕&#xff0c;任意组合分辨率。可用于简单仪表显…

1、VMware虚拟机及网络配置

一、VMware虚拟网络编辑器 1、选择NAT模式并配置子网 2、进入NAT设置&#xff0c;配置网关 3、宿主机网络适配器设置 二、创建虚拟机 在这里插入图片描述 三、开启虚拟机&#xff0c;安装操作系统 在该网段内配置静态ip&#xff0c;指定网关为前面NAT配置的网关地址…

Java8 BiConsumer<T, U> 函数接口浅析分享(含示例,来戳!)

文章目录 Java8 BiConsumer<T, U> 函数接口浅析分享&#xff08;含示例&#xff0c;来戳&#xff01;&#xff09;源码accept 方法示例示例一示例二 andThen 方法示例示例一示例二 示例相关代码类dohandler 方法student.javaStudentScore.javaStudentScoreDto.java Java8…

运行报错(三)git bash报错fatal: detected dubious ownership in repository at

报错现象 在运行git 命令时&#xff0c;出现报错 “fatal: detected dubious ownership in repository at” 报错原因 文件夹的所有者和现在的用户不一致 栗子&#xff1a; 文件夹的所有者是root&#xff0c;而当前用户是admin 解决方案 方法一、 将文件夹的所有者替换成ad…

【JAVA学习一:基础语法】

记录学习过程和代码编写&#xff0c;小白纯属记录。 目录 一、运算符 二、数组 三、面向对象 一、运算符 赋值运算符 public class Demo01 { public static void main(String[] args){ System.out.println(11); System.out.println(1-1); System.out.printl…