当前位置: 首页 > news >正文

【组件库】使用Vue2+AntV X6+ElementUI 实现拖拽配置自定义vue节点

    先来看看实现效果:
在这里插入图片描述

    【组件库】使用 AntV X6 + ElementUI 实现拖拽配置自定义 Vue 节点
在现代前端开发中,流程图和可视化编辑器的需求日益增加。AntV X6 是一个强大的图形化框架,支持丰富的图形操作和自定义功能。结合 ElementUI,我们可以轻松实现一个基于 Vue 的拖拽配置流程图,支持自定义节点和动态字段编辑。

一、技术栈介绍

AntV X6:一个基于 HTML5 Canvas 的图形化框架,支持流程图、拓扑图等多种图形化场景。

  • ElementUI:一个基于 Vue 的 UI 组件库,提供丰富的表单、表格和弹窗组件。
  • Vue.js:一个渐进式 JavaScript 框架,用于构建用户界面。

二、项目需求

我们的目标是实现一个流程图编辑器,支持以下功能:
拖拽添加节点:用户可以通过拖拽的方式在画布上添加自定义节点。
节点配置:通过弹窗对话框配置节点的属性,包括实体名称和字段信息。
字段动态编辑:支持动态添加、删除字段,并提供字段类型选择。
数据导入导出:支持从 JSON 文件导入数据,以及将当前流程图导出为 JSON 文件。

三、实现步骤

1. 初始化项目

首先,确保你已经安装了 Vue CLI 和相关依赖。创建一个新的 Vue 项目,并安装以下依赖:

vue create x6-vue-flow
cd x6-vue-flow
npm install @antv/x6 @antv/x6-plugin-dnd @antv/x6-vue-shape element-ui

2. 创建主组件

在 src/components/FlowEditor.vue 中,实现流程图编辑器的主组件。以下是核心代码:

<template><div class="flow-container"><!-- 导航栏 --><div class="flow-nav"><div class="add-entity" @mousedown="startDrag">添加实体</div><el-button type="primary" plain size="medium">保存</el-button><el-button type="warning" plain size="medium">清空</el-button><el-button type="success" plain size="medium">导出</el-button><el-upload accept=".json" :on-progress="handleOnProgress" action="" :show-file-list="false"><el-button plain size="primary">导入</el-button></el-upload></div><!-- 画布 --><div class="flow-content"><div id="container"></div></div><!-- 实体编辑对话框 --><el-dialog title="新增实体" :visible.sync="dialogVisible" width="45%"><el-form ref="form" :model="formData" label-width="130px" :rules="rules" size="small"><el-form-item prop="entity_name_CN" label="逻辑实体中文名"><el-input v-model="formData.entity_name_CN" clearable></el-input></el-form-item><el-form-item prop="entity_name_EN" label="逻辑实体英文名"><el-input v-model="formData.entity_name_EN" clearable></el-input></el-form-item><div class="field-container"><div class="field-container__title"><div class="primary-title">字段信息</div><el-button type="primary" size="small" icon="el-icon-plus" @click="addField">新增一行</el-button></div><el-table :data="formData.formField" height="250"><el-table-column type="index" width="50" label="序号" align="center"></el-table-column><el-table-column prop="cname" label="字段中文名" width="150" align="center"><template v-slot:default="{ $index }"><el-input size="small" v-model="formData.formField[$index].cname"></el-input></template></el-table-column><el-table-column prop="ename" label="字段英文名" width="200" align="center"><template v-slot:default="{ $index }"><el-input size="small" v-model="formData.formField[$index].ename"></el-input></template></el-table-column><el-table-column prop="efType" label="字段类型" align="center"><template v-slot:default="{ $index }"><el-select v-model="formData.formField[$index].efType" size="small"><el-option v-for="item in options" :key="item" :label="item" :value="item"></el-option></el-select></template></el-table-column><el-table-column label="操作" fixed="right" align="center" width="80"><template v-slot:default="{ $index }"><el-button type="danger" size="small" @click="handleFieldDelete($index)">删除</el-button></template></el-table-column></el-table></div></el-form><span slot="footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="onSubmit(formData)">确定</el-button></span></el-dialog></div>
</template><script>
import { Graph, Shape } from '@antv/x6';
import { Dnd } from '@antv/x6-plugin-dnd';
import { register } from '@antv/x6-vue-shape';
import CellNode from './CellNode.vue';export default {name: 'FlowEditor',data() {return {graph: null,dialogVisible: false,formData: {entity_name_CN: '',entity_name_EN: '',formField: [{ cname: '', ename: '', efType: '' }],},options: ['STRING', 'NUMBER', 'BOOLEAN', 'DATE', 'EMAIL'],};},mounted() {this.$nextTick(() => {this.initGraph();});},methods: {initGraph() {const container = document.getElementById('container');const config = {container,width: '100%',height: '100%',autoResize: true,panning: true,mousewheel: true,};this.graph = new Graph(config);const dnd = new Dnd({target: this.graph,validateNode: (node) => {this.currentDragNode = node;this.dialogVisible = true;return false;},});this.dnd = dnd;},startDrag(e) {const node = this.graph.createNode({shape: 'CellNode',});this.dnd.start(node, e);},onSubmit(data) {this.dialogVisible = false;const node = this.graph.addNode(this.currentDragNode);node.setData(data);},addField() {this.formData.formField.push({ cname: '', ename: '', efType: '' });},handleFieldDelete(index) {this.formData.formField.splice(index, 1);},},
};
</script>

3. 创建自定义 Vue 节点

在 src/components/CellNode.vue 中,实现自定义的 Vue 节点组件。以下是代码:

<template><div style="background-color: #ffffff;"><el-table :data="formData.formField" style="width: 100%" height="250"><el-table-column label="资源名称" :formatter="() => formData.entity_name_CN"></el-table-column><el-table-column prop="cname" label="中文名"></el-table-column><el-table-column prop="ename" label="英文名"></el-table-column><el-table-column prop="efType" label="类型"></el-table-column></el-table></div>
</template><script>
export default {name: 'CellNode',inject: ['getNode'],data() {return {node: null,formData: {entity_name_CN: '',entity_name_EN: '',formField: [{ cname: '', ename: '', efType: '' }],},};},mounted() {const node = this.getNode();this.node = node;node.on('change:data', (data) => {if (data.cell && data.cell.data) {this.formData = node.getData();}});},
};
## 4. 注册自定义节点 在主组件中,使用 @antv/x6-vue-shape 注册自定义的 Vue 节点:
import { register } from '@antv/x6-vue-shape';
import CellNode from './CellNode.vue';register({shape: 'CellNode',width: 300,height: 250,component: CellNode,
});
  1. 样式优化
    在 src/styles/index.scss 中,添加全局样式:
.flow-container {width: 100%;height: 100%;display: flex;flex-direction: column;.flow-nav {display: flex;align-items: center;margin-bottom: 5px;.add-entity {border-radius: 6px;background: rgba(64, 158, 255, 0.7);border-color: #409eff;border-style: dashed;text-align: center;color: #fff;font-size: 14px;padding: 5px;box-sizing: content-box;width: 100px;cursor: pointer;}}.flow-content {flex: 1;}
}

四、运行项目

完成以上步骤后,运行项目:

npm run serve

打开浏览器访问 http://localhost:8080,你将看到一个支持拖拽添加节点、动态字段编辑的流程图编辑器。

五、总结

    通过 AntV X6 和 ElementUI 的结合,我们实现了一个功能丰富的流程图编辑器。AntV X6 提供了强大的图形化能力,ElementUI 提供了丰富的 UI 组件,两者结合可以快速搭建出高效的可视化工具。

完整代码

Graph.vue代码

// Graph.vue
<template><div class="flow-container"><!-- 导航栏 --><div class="flow-nav"><div class="add-entity" @mousedown="startDrag">添加实体</div><el-button type="primary" style="margin-left: 10px" plain  size="medium">保存</el-button><el-button type="warning" style="margin-left: 10px" plain size="medium">清空</el-button><el-button type="success" style="margin-left: 10px" plain  size="medium">导出</el-button><el-upload accept=".JSON" :on-progress="handleOnProgress" action="" :show-file-list="false"><el-button plain size="primary" style="margin-left: 10px">导入</el-button></el-upload></div><!-- 画布 --><div class="flow-content" ><div id="container"></div></div><!-- 实体编辑对话框 --><el-dialog class="dialog-box" title="新增实体" :visible.sync="dialogVisible" width="45%"  :before-close="handleClose" append-to-body="false"><div class="content-wrapper"><div class="primary-title">基本信息</div><el-formref="form":model="formData"label-width="130px":rules="rules"size="small"><el-form-item prop="entity_name_CN" label="逻辑实体中文名"><el-input v-model="formData.entity_name_CN" clearable></el-input></el-form-item><el-form-item prop="entity_name_EN" label="逻辑实体英文名"><el-input v-model="formData.entity_name_EN" clearable></el-input></el-form-item><div class="field-container"><div class="field-container__title"><div class="primary-title">字段信息</div><div class="field-operation"><el-buttontype="primary"size="small"icon="el-icon-plus"@click="addField">新增一行</el-button></div></div><el-table :data="formData.formField" label-position="center" height="250"><el-table-column type="index" width="50" label="序号" align="center"></el-table-column><el-table-columnproperty="cname"label="字段中文名"width="150"align="center"><template v-slot:default="{ $index }" ><el-input size="small" v-model="formData.formField[$index].cname"></el-input></template></el-table-column><el-table-columnproperty="ename"label="字段英文名"width="200"align="center"><template v-slot:default="{ $index }" ><el-input size="small" v-model="formData.formField[$index].ename"></el-input></template></el-table-column><el-table-columnproperty="efType"label="字段类型"align="center"><template v-slot:default="{ $index }"><el-selectv-model="formData.formField[$index].efType"default-first-optionplaceholder="请选择字段类型"clearablesize="small"><el-optionv-for="item in options":key="item":label="item":value="item"></el-option></el-select></template></el-table-column><el-table-column label="操作" fixed="right" align="center" width="80"><template v-slot:default="{ $index }"><el-buttontype="danger"size="small"@click="handleFieldDelete($index)">删除</el-button></template></el-table-column></el-table></div></el-form></div><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="onSubmit(formData)">确 定</el-button></span></el-dialog></div>
</template><script>
// import index from '../../index.js'
import { Graph, Shape } from '@antv/x6'
import { Dnd } from '@antv/x6-plugin-dnd'
import { register } from '@antv/x6-vue-shape'
import CellNode from './components/cellNode.vue'// 画布配置
const config = {container: null,width: '100%',height: '100%',autoResize: true,// 拖拽画布panning: true,mousewheel: true,connecting: {snap: true, // 是否开启连线自动吸附highlight: true, // 是否高亮显示连线router: 'manhattan',connectionPoint: 'anchor',anchor: 'center',allowBlank: false,// 不允许创建循环连线,即边的起始节点和终止节点为同一节点allowEdge: false,// 不允许起点终点相同allowLoop: false,//  是否允许边连接到非节点上allowNode: false,// 起始和终止节点的相同连接桩之间只允许创建一条边allowMulti: 'witPort'},background: {color: '#F2F7FA'},grid: {visible: true,type: 'doubleMesh',args: [{color: '#eee', // 主网格线颜色thickness: 1 // 主网格线宽度},{color: '#ddd', // 次网格线颜色thickness: 1, // 次网格线宽度factor: 4 // 主次网格线间隔}]}
}
// 连接桩配置
const ports = {groups: {// 对话框需要的一些外部数据right: {position: 'right',attrs: {circle: {r: 5,magnet: true,stroke: '#5F95FF',strokeWidth: 1,fill: '#fff'}}},left: {position: 'left',attrs: {circle: {r: 5,magnet: true,stroke: '#5F95FF',strokeWidth: 1,fill: '#fff'}}}}
}
// 注册HTML节点
Shape.HTML.register({shape: 'custom-html',width: 160,height: 80,effect: ['data'],html (formData) {const data = formDataconst div = document.createElement('div')div.className = 'custom-html'const span1 = document.createElement('span')const span2 = document.createElement('span')const span3 = document.createElement('span')span1.innerText = '1111'span2.innerText = '2222'span3.innerText = '3333'div.appendChild(span1)div.appendChild(span2)div.appendChild(span3)return div}
})
// 注册Vue节点
register({shape: 'CellNode',width: 300,height: 250,component: CellNode,ports: {...ports,items: [{ group: 'left' }, { group: 'right' }]}
})
// 注册边
Graph.registerEdge('dag-edge',{inherit: 'edge',attrs: {line: {stroke: '#C2C8D5',strokeWidth: 1,targetMarker: null}}},true
)export default {name: 'vue-flow',data () {return {graph: null,currentEdge: null,dnd: null,dialogVisible: false,currentDragNode: null,// 对话框类型 编辑/新增formData: {entity_name_CN: '',entity_name_EN: '',// field_list: [],formField: [{cname: '',ename: '',efType: ''}]},options: ['STRING','NUMBER','BOOLEAN','DATE','EMAIL','URL','ARRAY','OBJECT','TEXTAREA','SELECT','RADIO','CHECKBOX','PASSWORD','FILE','IMAGE','RANGE','COLOR','TEL','SEARCH','DATETIME','DATETIME_LOCAL','MONTH','WEEK','TIME','HIDDEN'],rules: {entity_name_CN: [{ required: true, trigger: 'blur', message: '请输入逻辑实体中文名' }],entity_name_EN: [{ required: true, trigger: 'blur', message: '请输入逻辑实体英文名' }]}}},provide () {return {// 要用箭头函数保证this在其他组件获取正确getGraph: () => {return this.graph}}},mounted () {this.$nextTick(() => {this.initGraph()})},methods: {initGraph () {// 容器domconst container = document.getElementById('container')config.container = container// 实例化画布this.graph = new Graph(config)// 实例化拖拽节点const dnd = new Dnd({target: this.graph,validateNode: (node) => {this.currentDragNode = nodethis.dialogVisible = truereturn false}})this.dnd = dndthis.graph.centerContent() // 居中显示},startDrag (e) {const node = this.graph.createNode({shape: 'CellNode'})this.dnd.start(node, e)},handleClose (done) {this.$confirm('确认关闭?').then(_ => {done()}).catch(_ => {})},// 添加节点addNode (node) {return this.graph.addNode(node)},onSubmit (data) {this.dialogVisible = falseif (this.currentDragNode) {const node = this.addNode(this.currentDragNode)const dataSource = {...data}// TODO 有异步问题需要处理先写死200mssetTimeout(() => {node.setData(dataSource)}, 200)}},addField () {this.formData.formField.push({cname: '',ename: '',efType: ''})},handleFieldDelete () {this.formData.formField.splice(0, 1)}}
}
</script><style lang="scss">
$height: 40px;
.custom-html {display: flex;width: 100%;height: 100%;align-items: center;background-color: #fff;span {display: inline-block;height: $height;line-height: $height;border: 1px solid #0f7bcc;text-align: center;min-width: 0;flex: 1;}
}.flow-container {width: 100%;height: 100%;display: flex;flex-direction: column;.flow-nav {display: flex;align-items: center;margin-bottom: 5px;.add-entity {border-radius: 6px;background: rgba(64, 158, 255, 0.7);background-clip: padding-box;border-color: #409eff;border-style: dashed;text-align: center;color: #fff;font-size: 14px;padding: 5px;box-sizing: content-box;width: 100px;cursor: pointer;}}.flow-content {flex: 1;}.my-selecting {border: 1px dashed #40ff7c;background-color: #0f7bcc;}.x6-widget-selection-box {border: 0px dashed rgba(0, 0, 0, 0);box-shadow: 1px 1px 10px 0 rgba(0, 0, 0, 0.3);border-radius: 6px;// background-color: #0F7BCC;// opacity: 0.1;}.x6-widget-selection-inner {opacity: 0.1;border: 5px solid #000000;background-color: #0f7bcc;}}
.dialog-box{// width: 600%;// height: 800px;.el-dialog__title{color:#fff;font-size: 18px;
}.content-wrapper {padding:15px;.primary-title {font-size: 18px;font-weight: 700;padding-bottom: 10px;}.field-container {&__title {display: flex;justify-content: space-between;}}
}
}
</style>

cellNode.vue代码

<template><div style="background-color:  #ffffff;"><el-table:data="formData.formField"style="width: 100%"height="250"><el-table-column :label="`资源名称:${formData.entity_name_CN}`"><el-table-columnprop="cname"label="中文名"></el-table-column><el-table-columnprop="ename"label="英文名"></el-table-column><el-table-columnprop="efType"label="类型"></el-table-column></el-table-column></el-table></div>
</template><script>
export default {name: 'CellNode',inject: ['getNode'],data () {return {// 当前实体节点node: null,formData: {entity_name_CN: '',entity_name_EN: '',formField: [{cname: '',ename: '',efType: ''}]}}},mounted () {// 获取node节点const node = this.getNode()this.node = node// 节点data改变监听node.on('change:data', (data) => {if (data.cell && data.cell.data) {this.formData = node.getData()console.log('🚀 ~ :', this.formData)}})}
}
</script>

相关文章:

【组件库】使用Vue2+AntV X6+ElementUI 实现拖拽配置自定义vue节点

先来看看实现效果&#xff1a; 【组件库】使用 AntV X6 ElementUI 实现拖拽配置自定义 Vue 节点 在现代前端开发中&#xff0c;流程图和可视化编辑器的需求日益增加。AntV X6 是一个强大的图形化框架&#xff0c;支持丰富的图形操作和自定义功能。结合 ElementUI&#xff0c;…...

Vue.js组件开发-如何实现全选反选

在 Vue.js 中实现全选和反选功能&#xff0c;可以通过结合v-model、计算属性和事件处理来完成。 实现思路 • 数据绑定&#xff1a;为每个复选框绑定一个选中状态。 • 全选控制&#xff1a;通过一个复选框控制所有复选框的选中状态。 • 反选控制&#xff1a;通过一个按钮或…...

2025.1.20——四、[强网杯 2019]Upload1 文件上传|反序列化

题目来源&#xff1a;buuctf [强网杯 2019]Upload 1 目录 一、打开靶机&#xff0c;查看信息 二、解题思路 step 1&#xff1a;登陆进去看情况 step 2&#xff1a;大佬来支援——问题在cookie step 3&#xff1a;测试两个思路 1.目录穿越 2.目录扫描 step 4&#xff…...

php代码审计2 piwigo CMS in_array()函数漏洞

php代码审计2 piwigo CMS in_array()函数漏洞 一、目的 本次学习目的是了解in_array()函数和对项目piwigo中关于in_array()函数存在漏洞的一个审计并利用漏洞获得管理员帐号。 二、in_array函数学习 in_array() 函数搜索数组中是否存在指定的值。 in_array($search,$array…...

docker搭建redis集群(三主三从)

本篇文章不包含理论解释&#xff0c;直接开始集群&#xff08;三主三从&#xff09;搭建 环境 centos7 docker 26.1.4 redis latest &#xff08;7.4.2&#xff09; 服务器搭建以及环境配置 请查看本系列前几篇博客 默认已搭建好三个虚拟机并安装配置好docker 相关博客&#xf…...

[Datawheel]利用Zigent框架编写智能体-1

1.背景知识 1.1 什么是zigent&#xff1f; Zigent 是一个多智能体框架&#xff0c;旨在简化和优化智能体的开发与部署。Zigent 是由 自塾&#xff08;Zishu.co&#xff09; 团队开发的一个开源项目。自塾在 2024 年推出了多个开源项目&#xff0c;其中包括 wow-agent&#xf…...

【计算机视觉】人脸识别

一、简介 人脸识别是将图像或者视频帧中的人脸与数据库中的人脸进行对比&#xff0c;判断输入人脸是否与数据库中的某一张人脸匹配&#xff0c;即判断输入人脸是谁或者判断输入人脸是否是数据库中的某个人。 人脸识别属于1&#xff1a;N的比对&#xff0c;输入人脸身份是1&…...

linux环境变量配置文件区别 /etc/profile和~/.bash_profile

在 Linux 系统中&#xff0c;环境变量可以定义用户会话的行为&#xff0c;而这些变量的加载和配置通常涉及多个文件&#xff0c;如 ~/.bash_profile 和 /etc/profile。这些文件的作用和加载时机各有不同。以下是对它们的详细区别和用途的说明&#xff1a; 文章目录 1. 环境变量…...

mac 配置 python 环境变量

最新 mac 电脑&#xff0c;配置原理暂未研究&#xff0c;欢迎答疑 方案一 获取python的安装路径 which python3 配置环境变量 open ~/.bash_profile 末尾添加&#xff1a; PATH"/Library/Frameworks/Python.framework/Versions/3.13/bin:${PATH}" export PATH …...

终极的复杂,是简单

软件仿真拥有最佳的信号可见性和调试灵活性,能够高效捕获很多显而易见的常见错误,被大多数工程师熟练使用。 空间领域应用的一套数据处理系统(Data Handling System),采用抗辐FPGA作为主处理器,片上资源只包含10752个寄存器,软仿也是个挺花时间的事。 Few ms might take …...

软件开发中的密码学(国密算法)

1.软件行业中的加解密 在软件行业中&#xff0c;加解密技术广泛应用于数据保护、通信安全、身份验证等多个领域。加密&#xff08;Encryption&#xff09;是将明文数据转换为密文的过程&#xff0c;而解密&#xff08;Decryption&#xff09;则是将密文恢复为明文的过程。以下…...

【豆包MarsCode 蛇年编程大作战】蛇形烟花

项目体验地址&#xff1a;项目体验地址 官方活动地址&#xff1a;活动地址 目录 【豆包MarsCode 蛇年编程大作战】蛇形烟花演示 引言 豆包 MarsCode介绍 项目准备 第一步&#xff1a;安装插件 第二步&#xff1a;点击豆包图标来进行使用豆包 使用豆包 MarsCodeAI助手实…...

Jmeter使用Request URL请求接口

简介 在Jmeter调试接口时&#xff0c;有时不清楚后端服务接口的具体路径&#xff0c;可以使用Request URL和cookie来实现接口请求。以下内容以使用cookie鉴权的接口举例。 步骤 ① 登录网站后获取具体的Request URL和cookie信息 通过浏览器获取到Request URL和cookie&#…...

使用Pytest Fixtures来提升TestCase的可读性、高效性

关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 在编写单元测试时&#xff0c;你是否发现自己有很多重复代码&#xff1f; 数据库设…...

Arduino大师练成手册 -- 读取DHT11

要在 Arduino 上控制 DHT11 温湿度传感器&#xff0c;你可以按照以下步骤进行&#xff1a; 硬件连接&#xff1a; 将 DHT11 的 VCC 引脚连接到 Arduino 的 5V 引脚。 将 DHT11 的 GND 引脚连接到 Arduino 的 GND 引脚。 将 DHT11 的 DATA 引脚连接到 Arduino 的数字引脚&am…...

【Jave全栈】Java与JavaScript比较

文章目录 前言一、Java1、 历史与背景2、语言特点3、应用场景4、生态系统 二、JavaScript1、历史与背景2、语言特点3、应用场景4、 生态系统 三、相同点四、不同点1、语言类型2、用途3、语法和结构4、性能5、生态系统6、开发模式 前言 Java和JavaScript是两种不同的编程语言&a…...

【高项】6.2 定义活动 ITTO

定义活动是识别和记录为完成项目可交付成果而须采取的具体行动的过程。 作用&#xff1a;将工作包分解为进度活动&#xff0c;作为对项目工作进行进度估算、规划、执行、监督和控制的基础 输入 项目管理计划 ① 进度管理计划&#xff1a;定义进度计划方法、滚动式规划的持续…...

openlava/LSF 用户组管理脚本

背景 在openlava运维中经常需要自动化一些常规操作&#xff0c;比如增加用户组以及组成员、删除用户组成员、删除用户组等。而openlava的配置文件需要手动修改&#xff0c;然后再通过badmin reconfig激活配置。因此开发脚本将手工操作自动化就很有必要。 通过将脚本中的User…...

数据结构与算法之贪心: LeetCode 649. Dota2 参议院 (Ts版)

Dota2 参议院 https://leetcode.cn/problems/dota2-senate/ 描述 Dota2 的世界里有两个阵营&#xff1a;Radiant&#xff08;天辉&#xff09;和 Dire&#xff08;夜魇&#xff09; Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。…...

西藏酥油茶:高原上的醇香温暖

西藏酥油茶:高原上的醇香温暖 在西藏高原,有一种饮品,它不仅滋养了一代又一代的藏民,还承载着丰富的文化与历史,它就是西藏酥油茶。酥油茶,藏语称为“恰苏玛”,意为搅动的茶,是藏族人民日常生活中不可或缺的一部分,更是待客、祭祀等活动中的重要礼仪物品。 历史与文化渊源 酥…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

SFTrack:面向警务无人机的自适应多目标跟踪算法——突破小尺度高速运动目标的追踪瓶颈

【导读】 本文针对无人机&#xff08;UAV&#xff09;视频中目标尺寸小、运动快导致的多目标跟踪难题&#xff0c;提出一种更简单高效的方法。核心创新在于从低置信度检测启动跟踪&#xff08;贴合无人机场景特性&#xff09;&#xff0c;并改进传统外观匹配算法以关联此类检测…...

RFID推动新能源汽车零部件生产系统管理应用案例

RFID推动新能源汽车零部件生产系统管理应用案例 一、项目背景 新能源汽车零部件场景 在新能源汽车零部件生产领域&#xff0c;电子冷却水泵等关键部件的装配溯源需求日益增长。传统 RFID 溯源方案采用 “网关 RFID 读写头” 模式&#xff0c;存在单点位单独头溯源、网关布线…...