基于jeecg-boot的flowable流程收回功能实现(全网首创功能)

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

gitee源代码地址

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

前端代码:https://gitee.com/nbacheng/nbcio-vue.git

在线演示(包括H5) : http://122.227.135.243:9888
       

      对于之前的flowable流程,之前有撤回,拒绝,退回等功能,但都不能满足发起人对于流程收回的功能,发起人收回后可以重新进行流程发起,同时能够支持自定义业务的收回功能。

      从目前开源项目与全网的资料看都没有找到相关资料,所以只能自己来写相应的功能,满足用户的需求了。

      版权声明:大家要是单独用我的代码,请注明作者。

     1、首先前端功能

       前端比较简单,只要在已办功能里增加收回菜单功能,同时调用后端代码来实现。

        增加一个菜单按钮

      增加一个收回任务函数

      完整的代码如下:

<template><a-card :bordered="false"><!-- 查询区域 --><div class="table-page-search-wrapper"><a-form layout="inline" @keyup.enter.native="handleQuery"><a-row :gutter="24"><a-col :md="6" :sm="8"><a-form-item label="流程名称"><a-input placeholder="请输入流程名称" v-model="queryParams.procDefName"></a-input></a-form-item></a-col><a-col :md="8" :sm="24"><a-form-item label="接收日期"><a-date-picker v-model="queryParams.createTime"  style="width: 100%" placeholder="请输入接收日期"/></a-form-item></a-col><a-col :md="6" :sm="8"><span style="float: left;overflow: hidden;" class="table-page-search-submitButtons"><a-button type="primary" @click="handleQuery" icon="search">查询</a-button><a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button></span></a-col></a-row></a-form></div><!-- 查询区域-END --><!-- 操作按钮区域 --><div class="table-operator"><a-button type="primary" icon="download" @click="handleExportXls('待办任务')">导出</a-button><a-dropdown v-if="selectedRowKeys.length > 0"><a-menu slot="overlay"><a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item></a-menu><a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button></a-dropdown></div><!-- table区域-begin --><div><div class="ant-alert ant-alert-info" style="margin-bottom: 16px;"><i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项<a style="margin-left: 24px" @click="onClearSelected">清空</a></div><a-tableref="table"size="middle":scroll="{x:true}"borderedrowKey="procInsId":columns="columns":dataSource="dataSource":pagination="ipagination":loading="loading":rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"class="j-table-force-nowrap"@change="handleTableChange"><template slot="procDefVersion" slot-scope="text, record, index"><el-tag size="medium" >V{{ record.procDefVersion }}</el-tag></template><template slot="startUserName" slot-scope="text, record, index"><label>{{record.startUserName}} <el-tag type="info" size="mini">{{record.startDeptName}}</el-tag></label></template><template slot="htmlSlot" slot-scope="text"><div v-html="text"></div> </template><template slot="imgSlot" slot-scope="text"><span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span><img v-else :src="getImgView(text)" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/></template><template slot="fileSlot" slot-scope="text"><span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span><a-buttonv-else:ghost="true"type="primary"icon="download"size="small"@click="downloadFile(text)">下载</a-button></template><span slot="action" slot-scope="text, record"><a-dropdown><a class="ant-dropdown-link">更多 <a-icon type="down" /></a><a-menu slot="overlay"><a-menu-item><a @click="handleFlowRecord(record)">流转记录</a></a-menu-item><a-menu-item><a @click="handleRecall(record)"> 收回</a></a-menu-item><a-menu-item><a @click="handleRevoke(record)"> 撤回</a></a-menu-item></a-menu></a-dropdown></span></a-table></div></a-card>
</template><script>import '@/assets/less/TableExpand.less'import { mixinDevice } from '@/utils/mixin'import { JeecgListMixin } from '@/mixins/JeecgListMixin'  import { finishedList, finishedListNew, getDeployment, delDeployment, addDeployment, updateDeployment, exportDeployment, revokeProcess, recallProcess } from "@/views/flowable/api/finished";import moment from 'moment';
export default {name: "finishedIndex",mixins:[JeecgListMixin, mixinDevice],components: {},data() {return {// 表头columns: [{title: '#',dataIndex: '',key:'rowIndex',width:60,align:"center",customRender:function (t,r,index) {return parseInt(index)+1;}},{title:'任务编号',align:"center",dataIndex: 'procInsId',},{title:'流程名称',align:"center",dataIndex: 'procDefName',},{title:'任务节点',align:"center",dataIndex: 'taskName',},{title:'流程类别',align:"center",dataIndex: 'category'},{title:'流程版本',align:"center",dataIndex: 'procDefVersion',scopedSlots: { customRender: 'procDefVersion' }},{title:'业务主键',align:"center",dataIndex: 'businessKey'},{title:'流程发起人',align:"center",dataIndex: 'startUserName',scopedSlots: { customRender: 'startUserName' }},{title:'接收时间',align:"center",dataIndex: 'createTime'},{title:'审批时间',align:"center",dataIndex: 'finishTime'},{title:'耗时',align:"center",dataIndex: 'duration'},{title: '操作',dataIndex: 'action',align:"center",fixed:"right",width:147,scopedSlots: { customRender: 'action' }}],// 查询参数queryParams: {pageNo: 1,pageSize: 10,name: null,category: null,key: null,tenantId: null,deployTime: null,derivedFrom: null,derivedFromRoot: null,parentDeploymentId: null,engineVersion: null,procDefName: null,createTime: null},url: {list: "/flowable/task/finishedListNew",deleteBatch: "/flowable/task/deleteBatch",exportXlsUrl: "/flowable/task/finishedExportXls",},dataSource: [], //表格数据源/* 表格分页参数 */ipagination:{current: 1,pageSize: 10,pageSizeOptions: ['10', '20', '30'],showTotal: (total, range) => {return range[0] + "-" + range[1] + " 共" + total + "条"},showQuickJumper: true,showSizeChanger: true,total: 0},// 遮罩层loading: true,// 选中数组ids: [],// 非单个禁用single: true,// 非多个禁用multiple: true,// 显示搜索条件showSearch: true,// 总条数total: 0,// 已办任务列表数据finishedList: [],// 弹出层标题title: "",// 是否显示弹出层open: false,src: "",// 查询参数queryParams: {pageNo: 1,pageSize: 10,name: null,category: null,key: null,tenantId: null,deployTime: null,derivedFrom: null,derivedFromRoot: null,parentDeploymentId: null,engineVersion: null},// 表单参数form: {},// 表单校验rules: {}};},created() {this.getSuperFieldList();//this.getList();},methods: {/** 查询流程定义列表 */getList() {this.loading = true;finishedListNew(this.queryParams).then(response => {if(response.success) {this.dataSource = response.result.records;this.total = response.result.total;this.ipagination.total = response.result.total;   this.loading = false;}else {this.$message.error(response.message)this.loading = false;}});},// 取消按钮cancel() {this.open = false;this.reset();},// 表单重置reset() {this.form = {id: null,name: null,category: null,key: null,tenantId: null,deployTime: null,derivedFrom: null,derivedFromRoot: null,parentDeploymentId: null,engineVersion: null};this.resetForm("form");},setIcon(val){if (val){return "el-icon-check";}else {return "el-icon-time";}},setColor(val){if (val){return "#2bc418";}else {return "#b3bdbb";}},initDictConfig(){},getSuperFieldList(){let fieldList=[];fieldList.push({type:'string',value:'procInsId',text:'任务编号'})fieldList.push({type:'string',value:'procDefName',text:'流程名称'})fieldList.push({type:'string',value:'taskName',text:'任务节点'})fieldList.push({type:'string',value:'category',text:'流程类别'})fieldList.push({type:'string',value: 'procDefVersion',text:'流程版本'})fieldList.push({type:'string',value: 'businessKey',text:'业务主键'})fieldList.push({type:'string',value:'startUserName',text:'流程发起人'})fieldList.push({type:'datetime',value:'createTime',text:'接收时间'})fieldList.push({type:'datetime',value:'finishTime',text:'审批时间'})fieldList.push({type:'string',value:'duration',text:'耗时'})this.superFieldList = fieldList},/** 搜索按钮操作 */handleQuery() {this.queryParams.pageNum = 1;this.getList();},/** 重置按钮操作 */resetQuery() {this.resetForm("queryForm");this.handleQuery();},// 多选框选中数据handleSelectionChange(selection) {this.ids = selection.map(item => item.id)this.single = selection.length!==1this.multiple = !selection.length},/** 新增按钮操作 */handleAdd() {this.reset();this.open = true;this.title = "添加流程定义";},/** 流程流转记录 */handleFlowRecord(row){this.$router.push({ path: '/flowable/task/record/index',query: {procInsId: row.procInsId,deployId: row.deployId,taskId: row.taskId,businessKey: row.businessKey,category: row.category,finished: false}})},/** 撤回任务 */handleRevoke(row){const params = {instanceId: row.procInsId,dataId: row.businessKey}revokeProcess(params).then( res => {this.$message.success(res.message);this.getList();});},/** 收回任务 */handleRecall(row){const params = {instanceId: row.procInsId,dataId: row.businessKey}recallProcess(params).then( res => {this.$message.success(res.message);this.getList();});},/** 提交按钮 */submitForm() {this.$refs["form"].validate(valid => {if (valid) {if (this.form.id != null) {updateDeployment(this.form).then(response => {this.$message.success("修改成功");this.open = false;this.getList();});} else {addDeployment(this.form).then(response => {this.$message.success("新增成功");this.open = false;this.getList();});}}});},/** 删除按钮操作 */handleDelete(row) {const ids = row.id || this.ids;const dataid = row.businessKey; this.$confirm('是否确认删除流程定义编号为"' + ids + '"的数据项?', "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(function() {return delDeployment(ids,dataid);}).then(() => {this.getList();this.$message.success("删除成功");})},/** 导出按钮操作 */handleExport() {const queryParams = this.queryParams;this.$confirm('是否确认导出所有流程定义数据项?', "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(function() {return exportDeployment(queryParams);}).then(response => {this.download(response.message);})}}
};
</script>

2、后端代码

    2.1  增加一个收回流程功能recallProcess,具体代码如下:

/***  发起人收回流程*  add by nbacheng*           * @param FlowTaskVo taskVo*           * @return*/@Override@Transactionalpublic Result recallProcess(FlowTaskVo flowTaskVo) {// 当前任务 listtaskList<Task>  listtask = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).active().list();if (listtask == null) {throw new CustomException("流程未启动或已执行完成,无法收回");}if (taskService.createTaskQuery().taskId(listtask.get(0).getId()).singleResult().isSuspended()) {throw new CustomException("任务处于挂起状态");}List<Task> procInsId = taskService.createNativeTaskQuery().sql("select * from ACT_HI_TASKINST where PROC_INST_ID_ = #{procInsId} ORDER BY START_TIME_ desc").parameter("procInsId", flowTaskVo.getInstanceId()).list();SysUser loginUser = iFlowThirdService.getLoginUser();String processInstanceId = listtask.get(0).getProcessInstanceId();//  获取所有历史任务(按创建时间升序)List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();if (CollectionUtil.isEmpty(hisTaskList) || hisTaskList.size() < 2) {log.error("当前流程 【{}】 审批节点 【{}】正在初始节点无法收回", processInstanceId, listtask.get(0).getName());throw new FlowableException(String.format("当前流程 【%s】 审批节点【%s】正在初始节点无法收回", processInstanceId, listtask.get(0).getName()));}//  第一个任务HistoricTaskInstance startTask = hisTaskList.get(0);//若操作用户不是发起人,不能收回if(!StringUtils.equalsAnyIgnoreCase(loginUser.getUsername(), startTask.getAssignee())) {throw new CustomException("操作用户不是发起人,不能收回");}//  当前任务HistoricTaskInstance currentTask = hisTaskList.get(hisTaskList.size() - 1);BpmnModel bpmnModel = repositoryService.getBpmnModel(listtask.get(0).getProcessDefinitionId());//  获取第一个活动节点FlowNode startFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(startTask.getTaskDefinitionKey());//  获取当前活动节点FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentTask.getTaskDefinitionKey());//  临时保存当前活动的原始方向List<SequenceFlow> originalSequenceFlowList = new ArrayList<>(currentFlowNode.getOutgoingFlows());//  清理活动方向currentFlowNode.getOutgoingFlows().clear();//  建立新方向SequenceFlow newSequenceFlow = new SequenceFlow();newSequenceFlow.setId("newSequenceFlowId");newSequenceFlow.setSourceFlowElement(currentFlowNode);newSequenceFlow.setTargetFlowElement(startFlowNode);List<SequenceFlow> newSequenceFlowList = new ArrayList<>();newSequenceFlowList.add(newSequenceFlow);//  当前节点指向新的方向currentFlowNode.setOutgoingFlows(newSequenceFlowList);//  完成当前任务for(Task task : listtask) {taskService.addComment(task.getId(), listtask.get(0).getProcessInstanceId(),FlowComment.RECALL.getType(), "发起人收回");taskService.setAssignee(task.getId(), startTask.getAssignee());taskService.complete(task.getId());}//  重新查询当前任务Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();if (ObjectUtil.isNotNull(nextTask)) {taskService.setAssignee(nextTask.getId(), startTask.getAssignee());//taskService.complete(nextTask.getId());;//跳过流程发起节点}//自定义业务处理idString dataId = flowTaskVo.getDataId();// 删除运行和历史的节点信息 this.deleteActivity(procInsId.get(1).getTaskDefinitionKey(), flowTaskVo.getInstanceId(), dataId);//  恢复原始方向currentFlowNode.setOutgoingFlows(originalSequenceFlowList);//自定义业务处理if(StrUtil.isNotBlank(flowTaskVo.getDataId()) && !Objects.equals(flowTaskVo.getDataId(), "null")){//如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);//删除自定义业务任务关联表,以便可以重新发起流程if (business != null) {flowMyBusinessService.removeById(business);}}return Result.OK("发起人收回成功");}

   2.2 调用 删除历史节点信息deleteActivity

/*** 删除跳转的历史节点信息** @param disActivityId     跳转的节点id* @param processInstanceId 流程实例id* @param dataId   自定义业务id*/protected void deleteActivity(String disActivityId, String processInstanceId, String dataId) {List<ActivityInstance> disActivities = flowTaskMapper.queryActivityInstance(disActivityId, processInstanceId, null);//删除运行时和历史节点信息if (CollectionUtils.isNotEmpty(disActivities)) {ActivityInstance activityInstance = disActivities.get(0);List<ActivityInstance> datas = flowTaskMapper.queryActivityInstance(disActivityId, processInstanceId, activityInstance.getEndTime());//datas.remove(0); //保留流程发起节点信息List<String> runActivityIds = new ArrayList<>();if (CollectionUtils.isNotEmpty(datas)) {datas.forEach(ai -> runActivityIds.add(ai.getId()));flowTaskMapper.deleteRunActinstsByIds(runActivityIds);flowTaskMapper.deleteHisActinstsByIds(runActivityIds);}if(dataId != null) {//对于自定义业务, 删除所有相关流程信息//flowTaskMapper.deleteAllHisAndRun(processInstanceId);//根据流程实例id 删除去ACT_RU_*与ACT_HI_*流程实例数据ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();if (null != processInstance) {runtimeService.deleteProcessInstance(processInstanceId, "流程实例删除");historyService.deleteHistoricProcessInstance(processInstanceId);}}}}

2.3 FlowTaskMapper.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nbcio.modules.flowable.mapper.FlowTaskMapper"><select id="queryActivityInstance" resultType="org.flowable.engine.impl.persistence.entity.ActivityInstanceEntityImpl">select t.* fromact_ru_actinst t<where><if test="processInstanceId !=null and processInstanceId != ''" >t.PROC_INST_ID_=#{processInstanceId} and ACT_TYPE_ = 'userTask' and  END_TIME_ is not null </if></where>order by t.END_TIME_ ASC</select><delete id="deleteRunActinstsByIds" parameterType="java.util.List">delete from act_ru_actinst where ID_ in<foreach item="item" index="index" collection="list" open="(" separator="," close=")">#{item}</foreach></delete><delete id="deleteHisActinstsByIds" parameterType="java.util.List">delete from act_hi_actinst where ID_ in<foreach item="item" index="index" collection="list" open="(" separator="," close=")">#{item}</foreach></delete><delete id="deleteAllHisAndRun" parameterType="String">delete  from  act_ru_actinst  where proc_inst_id_ = #{processInstanceId}; delete  from  act_ru_identitylink  where proc_inst_id_ = #{processInstanceId};delete  from  act_ru_task  where proc_inst_id_ = #{processInstanceId};delete  from  act_ru_variable  where proc_inst_id_ = #{processInstanceId};delete  from  act_ru_execution  where proc_inst_id_ = #{processInstanceId};delete  from  act_hi_actinst where proc_inst_id_ = #{processInstanceId};delete  from  act_hi_comment where proc_inst_id_ = #{processInstanceId};delete  from  act_hi_identitylink  where proc_inst_id_ = #{processInstanceId};delete  from  act_hi_procinst where proc_inst_id_ = #{processInstanceId};delete  from  act_hi_taskinst where proc_inst_id_ = #{processInstanceId};delete  from  act_hi_varinst  where proc_inst_id_ = #{processInstanceId};</delete>
</mapper>

3、自定义业务与其它流程做分别处理

     其它流程直接删除相关用户任务历史信息,保留初始发送,用户可以直接进行流程重新编辑发送。

     而自定义业务则删除所有实例相关的任务历史信息,不保留任务相关信息,同时删除自定义业务发起时候的写入的关联表,以便用户可以再次发起流程。

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

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

相关文章

SpringBoot 的 RedisTemplate、Redisson

一、Jedis、Lettuce、Redisson的简介 优先使用Lettuce&#xff0c; 需要分布式锁&#xff0c;分布式集合等分布式的高级特性&#xff0c;添加Redisson结合使用。 对于高并发&#xff0c;1000/s的并发&#xff0c;数据库可能由行锁变成表锁&#xff0c;性能下降会厉害。 1.1、…

利用屏幕水印学习英语单词,无打扰英语单词学习

1、利用屏幕水印学习英语单词&#xff0c;不影响任何鼠标键盘操作&#xff0c;不影响工作 2、利用系统热键快速隐藏&#xff08;ALT1键 隐藏与显示&#xff09; 3、日积月累单词会有进步 4、软件下载地址: 免安装&#xff0c;代码未加密&#xff0c;安全的屏幕水印学习英语…

【云原生】3分钟快速在Kubernetes1.25部署Prometheus2.42+Grafana9.5.1+Alertmanager0.25

文章目录 1、简介2、GitHub地址3、环境信息4、安装5、访问Grafana1、简介 Prometheus-operator帮助我们快速创建Prometheus+Grafana+Alertmanager等服务,而kube-prometheus更加完整的帮助我们搭建全套监控体系,这包括部署多个 Prometheus 和 Alertmanager 实例, 指标导出器…

番茄(西红柿)叶病害识别(Python代码,pyTorch框架,深度卷积网络模型,很容易替换为其它模型,带有GUI识别界面)

代码运行要求&#xff1a;Torch>1.13.1即可 1.数据集介绍&#xff1a; 每一个文件夹里装有一类病害叶子的照片&#xff0c;一共10种类别&#xff0c;每种类别下有1100张照片 从第一类到第十类分别如下图所示 2.整体文件夹 data文件夹存放的是未被划分训练集和测试集的原…

解决Pycharm的Settings中Project不见了也无法选择Python Interpreter的方法

目录 一、问题如下二、解决方法 一、问题如下 突然打开项目没有python解释器&#xff0c;也无法重新配置python Interpreter&#xff0c;而且整个文件夹是黄色高亮的形式&#xff0c;如下显示&#xff0c;而且重新安装了pycharm也没用甚至说打开File–>Setting–>Projec…

PSP - 基于开源框架 OpenFold Multimer 蛋白质复合物的结构预测与BugFix

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132410296 AlphaFold2-Multimer 是一个基于 AlphaFold2 的神经网络模型&#xff0c;可以预测多链蛋白复合物的结构。该模型在训练和推理时都可以处…

回归预测 | MATLAB实现SCN随机配置网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SCN随机配置网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SCN随机配置网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本…

情报与GPT技术大幅降低鱼叉攻击成本

邮件鱼叉攻击&#xff08;spear phishing attack&#xff09;是一种高度定制化的网络诈骗手段&#xff0c;攻击者通常假装是受害人所熟知的公司或组织发送电子邮件&#xff0c;以骗取受害人的个人信息或企业机密。 以往邮件鱼叉攻击需要花费较多的时间去采集情报、深入了解受…

第三方软件测试机构可提供哪些测试服务?又有哪些注意事项?

软件测试是使用技术的手段&#xff0c;尽可能发现并改正软件中的错误&#xff0c;提高软件的可靠性及需求性&#xff0c;保障软件质量的过程。该过程也是软件开发完必不可少的一步&#xff0c;但国内还是有一些软件企业存在着“重开发&#xff0c;轻测试”的现象&#xff0c;上…

使用docker-maven-plugin插件构建镜像并推送至私服Harbor

前言 如下所示&#xff0c;建议使用 Dockerfile Maven 插件&#xff0c;但该插件也停止维护更新了。因此先暂时使用docker-maven-plugin插件。 一、开启Docker服务器的远程访问 1.1 开启2375远程访问 默认的dokcer是不支持远程访问的&#xff0c;需要加点配置&#xff0c;开…

php函数

函数是什么&#xff1f; 函数(function)是一段完成指定任务的已命名代码块。函数可以遵照给它的一组值或参数完成特定的任务&#xff0c;并且可能返回一个值。在PHP中有两种函数&#xff1a;自定义函数与系统函数。 函数就是可以完成固定功能的语句或语句集合&#xff0c;可以单…

Mac发现有的软件不能上网的破解之法

1、Mac上打开终端 terminal &#xff0c;获取 root 权限。 sudo -i 2、编辑 hosts 文件 vim /private/etc/hosts 3、找到被禁止软件的数据请求域名&#xff0c;然后删除相关行&#xff0c;快捷件dd&#xff0c;然后:wq保存退出 比如百度 127.0.0.1 pan.baidu.com ##sec 印…

前端编辑页面修改后和原始数据比较差异

在软件研发过程中&#xff0c;会遇到很多编辑页面&#xff0c;有时编辑页面和新增页面长的基本上一样&#xff0c;甚至就是一套页面供新增和编辑共用。编辑页面的场景比较多&#xff0c;例如&#xff1a; 场景一、字段比较多&#xff0c;但实际只修改了几个字段&#xff0c;如…

【网络层协议】ARP攻击与欺骗常见的手段以及工作原理

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、ARP攻击的常见手段 第一种&#xff1a;IP…

罗勇军 →《算法竞赛·快冲300题》每日一题:“超级骑士” ← DFS

【题目来源】http://oj.ecustacm.cn/problem.php?id1810http://oj.ecustacm.cn/viewnews.php?id1023https://www.acwing.com/problem/content/3887/【题目描述】 现在在一个无限大的平面上&#xff0c;给你一个超级骑士。 超级骑士有N种走法&#xff0c;请问这个超级骑士能否…

python刷小红书流量(小眼睛笔记访问量),metrics_report接口,原理及代码,以及x-s签名验证2023-08-21

一、什么是小眼睛笔记访问量 如下图所示&#xff0c;为笔记访问量。 二、小眼睛笔记访问量接口 1、url https://edith.xiaohongshu.com/api/sns/web/v1/note/metrics_report 2、payload data{"note_id": note_id,"note_type": note_type,"report_t…

SOFARPC(笔记)

文章目录 一、快速开始1.1 SOFARPC1.2 基于SOFABoot 二、注册中心三、通讯协议2.1 Bolt基本发布调用方式超时控制协议泛化调用序列化协议自定义线程池 2.2 RESTful基本使用 2.3 其他协议四、架构 附录 官方样例下载地址-sofa-boot-guides 可查看 SOFARPC 方式快速入门 一、快…

HTML5+CSS3+JS小实例:环形文字动画特效

实例:环形文字动画特效 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&quo…

深度解读波卡 2.0:多核、更有韧性、以应用为中心

本文基于 Polkadot 生态研究院整理&#xff0c;有所删节 随着波卡 1.0 的正式实现&#xff0c;波卡于 6 月 28 日至 29 日在哥本哈根举办了年度最重要的会议 Polkadot Decoded 2023&#xff0c;吸引了来自全球的行业专家、开发者和爱好者&#xff0c;共同探讨和分享波卡生态的…

C语言好题解析(四)

目录 选择题一选择题二选择题三选择题四选择题五编程题一 选择题一 已知函数的原型是&#xff1a; int fun(char b[10], int *a); 设定义&#xff1a; char c[10];int d; &#xff0c;正确的调用语句是&#xff08; &#xff09; A: fun(c,&d); B: fun(c,d); C: fun(&…