【sgTree】自定义组件:加载el-tree树节点整棵树数据,实现增删改操作。
特性
- 可以自定义主键、配置选项
- 支持预定义节点图标:folder文件夹|normal普通样式
- 多个提示文本可以自定义
- 支持动态接口增删改节点
- 可以自定义根节点id
- 可以设置最多允许添加的层级深度
- 支持拖拽排序,排序过程还可以针对拖拽的节点深度进行自定义限制
- 支持隐藏一级节点(根节点)复选框☑
- 支持屏蔽一级节点(根节点)勾选☑
sgTree源码
<template><div :class="$options.name"><div class="tree-header" v-if="!(readonly || readonly === '')"><div class="sg-left"><template v-if="uploadData"><el-tooltippopper-class="sg-el-tooltip":enterable="false"effect="dark":content="`支持拖拽到树上传文件`"placement="top-start"><el-buttontype="text"icon="el-icon-upload"size="mini"@click="(d) => $refs.sgUpload.triggerUploadFile()">批量导入</el-button></el-tooltip><el-button type="text" icon="el-icon-download" size="mini" @click="downloadTpl">下载模板</el-button></template></div><div class="sg-right"><el-button type="text" size="mini" @click.stop="addRoot">{{ (data.text || {}).addRootButtonText || `添加根节点`}}<i class="el-icon-circle-plus-outline"></i></el-button></div></div><div class="tree-container"><el-tree:class="hideRootNodeCheckbox === '' || hideRootNodeCheckbox? 'hideRootNodeCheckbox': ''"ref="tree":data="treeData":node-key="mainKey":props="data.props || {label: 'label', //指定节点标签为节点对象的某个属性值children: 'children', //指定子树为节点对象的某个属性值disabled: 'leaf', //指定节点选择框是否禁用为节点对象的某个属性值isLeaf: 'leaf', //指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效}":icon-class="`${data.iconType}-tree-node`":indent="data.indent || 10"@current-change="current_change"@node-click="nodeClick"highlight-current@node-drag-start="nodeDragStart"@node-drag-enter="nodeDragEnter"@node-drag-leave="nodeDragLeave"@node-drag-over="nodeDragOver"@node-drag-end="nodeDragEnd"@node-drop="nodeDrop":draggable="draggable === '' || draggable":allow-drop="allowDrop":allow-drag="allowDrag":show-checkbox="showCheckbox":default-checked-keys="defaultCheckedKeys"@check-change="handleCheckChange"><el-popoverpopper-class="tree-el-popover"placement="right"trigger="hover"title=""content="":disabled="readonly || readonly === ''"slot-scope="{ node, data }"><span class="right"><el-buttontitle="添加"type="text"size=""icon="el-icon-circle-plus-outline"@click.stop="addNode(node, data)"v-if="showAddButton(node)">添加</el-button><el-buttontitle="删除"type="text"size=""icon="el-icon-remove-outline"@click.stop="remove(node, data)">删除</el-button></span><div slot="reference" class="node-label"><div class="left" :title="node.label">{{ node.label }}</div></div></el-popover></el-tree><!-- 上传组件 --><sgUpload:disabledWhenShowSels="['.v-modal']":drag="uploadData ? dragUpload : false"ref="sgUpload":data="uploadData"@uploadSuccess="uploadSuccess"@uploadError="uploadError"@importError="importError"@showLoading="showLoading"@hideLoading="hideLoading"hideUploadTray/></div></div>
</template><script>
import sgUpload from "@/vue/components/admin/sgUpload";
export default {name: "sgTree",components: {sgUpload,},data() {return {// 动态树:增删改_________________________________________________________rootNode: null, //根节点rootResolve: null, //根节点focusNodeId: null, //聚焦高亮新添加IDmainKey: "id", //默认主键defaultRootId: "root", //默认根节点ID就是rootmaxAddLevel: null, // 最多允许添加的层级dragUpload: true, //在拖拽节点过程中控制上传组件能否拖拽上传// _________________________________________________________};},props: ["treeData","data","readonly","draggable", //是否开启拖拽节点功能"uploadData",/* 例子 uploadData: {accept: '.xls,.xlsx',actionUrl: `${this.$d.API_ROOT_URL}/core/resource/upload`,}, */"allowNodeDrag","allowNodeDrop","showCheckbox", //节点是否可被选择"hideRootNodeCheckbox", //隐藏一级节点复选框☑"disabledRootNode", //屏蔽一级节点勾选☑"defaultCheckedKeys", //默认勾选的节点的 key 的数组],watch: {data: {/* data.iconType= 节点图标:folder 文件夹normal 普通样式plus 加减符号样式*/handler(d) {d.nodeKey && (this.mainKey = d.nodeKey); //主键d.rootId && (this.defaultRootId = d.rootId); //根节点IDd.maxAddLevel && (this.maxAddLevel = d.maxAddLevel); // 最多允许添加的层级},deep: true,immediate: true,},},methods: {showLoading(file) {this.$emit(`showLoading`, file);},hideLoading(file) {this.$emit(`hideLoading`, file);},// 取消选中unCheckAll(d) {this.$refs.tree.setCheckedKeys([]);this.handleCheckChange([], []);},handleCheckChange(data, checked, indeterminate) {this.$emit(`checkChange`, {checkedNodes: this.$refs.tree.getCheckedNodes(),checkedLeafOnlyNodes: this.$refs.tree.getCheckedNodes(true, false), //(leafOnly, includeHalfChecked) 接收两个 boolean 类型的参数,1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false【注意:懒加载树形不管用!必须要明确叶子节点展开后面没有子节点了才能识别!】data,checked,indeterminate,});},// 拖拽----------------------------------------nodeDragStart(node, ev) {this.dragUpload = false;this.$emit(`nodeDragStart`, node, ev);},nodeDragEnter(draggingNode, dropNode, ev) {this.$emit(`nodeDragEnter`, draggingNode, dropNode, ev);},nodeDragLeave(draggingNode, dropNode, ev) {this.$emit(`nodeDragLeave`, draggingNode, dropNode, ev);},nodeDragOver(draggingNode, dropNode, ev) {this.$emit(`nodeDragOver`, draggingNode, dropNode, ev);},nodeDragEnd(draggingNode, dropNode, dropType, ev) {// dropType有'before'、'after'、'inner'和'none'4种情况this.dragUpload = true;this.$emit(`nodeDragEnd`, draggingNode, dropNode, dropType, ev);},nodeDrop(draggingNode, dropNode, dropType, ev) {// dropType有'before'、'after'、'inner'和'none'4种情况this.$emit(`nodeDrop`, draggingNode, dropNode, dropType, ev);},allowDrop(draggingNode, dropNode, dropType) {// 拖拽时判定目标节点能否被放置。dropType 参数有三种情况:'prev'、'inner' 和 'next',分别表示放置在目标节点前、插入至目标节点和放置在目标节点后(注意:很奇葩上面node开头的绑定方法dropType有before、after、inner和none4种情况)return this.allowNodeDrop? this.allowNodeDrop(draggingNode, dropNode, dropType): true;},allowDrag(draggingNode) {return this.allowNodeDrag ? this.allowNodeDrag(draggingNode) : true;},// ----------------------------------------showAddButton(node) {if (this.maxAddLevel) {return node.level < this.maxAddLevel; // 最多允许添加的层级} else return true;},downloadTpl(d) {this.$emit(`downloadTpl`);},uploadSuccess(d, f) {this.$emit(`uploadSuccess`, d, f);},uploadError(d, f) {this.$emit(`uploadError`, d, f);},importError(d, f) {this.$emit(`importError`, d, f);},// 聚焦到某一个节点focusNode(id) {if (!id) return;this.$nextTick(() => {this.$refs.tree.setCurrentKey(id); //高亮显示某个节点this.$emit(`currentChange`, this.$refs.tree.getCurrentNode());this.$nextTick(() => {let dom = document.querySelector(`.el-tree-node.is-current`);dom &&dom.scrollIntoView({behavior: "smooth",block: "nearest",inline: "nearest",}); //缓慢滚动});});},// 添加根节点addRoot() {this.addNode(this.$refs.tree.root, { [this.mainKey]: this.defaultRootId });},// 通过id展开指定节点(通常是用于外部调用)expandNodeById(id) {let node = this.$refs.tree.getNode(id);node.expand();},//通过id勾选节点setCheckedKeys(ids) {this.$refs.tree.setCheckedKeys(ids);},// 添加节点addNode(node, data) {let resolve = (d) => {if (data.ID === this.defaultRootId) {this.treeData.unshift(d);} else {data.children || this.$set(data, "children", []);data.children.push(d);}node.expand();};let reject = (d) => {this.rootLoading = false;node.loading = false;this.$message.error(d.msg); //添加节点失败};this.$emit(`addNode`, { node, data, resolve, reject });},// 删除节点remove(node, data) {this.$confirm((this.data.text || {}).removeConfirmTip ||`此操作将永久删除该节点及其下面的节点,是否继续?`,(this.data.text || {}).removeConfirmTitle || `提示`,{dangerouslyUseHTMLString: true,confirmButtonText: `确定`,cancelButtonText: `取消`,type: "warning",}).then(() => {this.removeNodeData(node, data);}).catch(() => {});},// 删除节点数据(通过接口向后台删除数据)removeNodeData(node, data) {node.loading = true; //出现加载动画let resolve = (d) => {node.loading = false;this.$message.success(`删除成功`);// 从父节点异步删除子节点const parent = node.parent;const children = parent.data.children || parent.data;const index = children.findIndex((d) => d[this.mainKey] === data[this.mainKey]);children.splice(index, 1);// 从显示界面删除节点(有bug,只是删除了树节点的Virtual DOM,实际数据还在)/* let childNodes = node.parent.childNodes; childNodes.splice( childNodes.findIndex((d) => d.data[this.mainKey] === data[this.mainKey]), 1 ); */};let reject = (d) => {this.rootLoading = false;node.loading = false;this.$message.error(d.msg); //删除失败};this.$emit(`removeNode`, { node, data, resolve, reject });},// 当前选中节点变化时触发的事件current_change(d) {this.$emit(`currentChange`, d);},//点击节点nodeClick(d) {this.focusNodeId = null;this.$emit(`nodeClick`, d);},},
};
</script><style lang="scss" scoped>
@import "~@/css/sg";.sgTree {$treeHeaderHeight: 30px;width: 100%;height: 100%;display: flex;flex-wrap: nowrap;flex-direction: column;white-space: nowrap;flex-shrink: 0;flex-grow: 1;position: relative;.tree-header {display: flex;justify-content: space-between;align-items: center;height: $treeHeaderHeight;& > .sg-left {}& > .sg-right {}}.tree-container {position: relative;overflow: auto;box-sizing: border-box;height: calc(100% - #{$treeHeaderHeight});flex-shrink: 0;flex-grow: 1;user-select: none;@include scrollbarHover();/* >>> .tree-container .el-tree .el-tree-node__content {cursor: pointer;} */>>> .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {background-color: #409eff22; // 高亮当前选中节点背景}>>> .el-tree {* {transition: none;}.el-tree-node__children {min-width: max-content; //这样才会出现水平滚动条}.normal-tree-node,.plus-tree-node,.folder-tree-node {& + label:not(.el-checkbox) {/*单行省略号*/overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}flex-shrink: 0;display: block;padding: 0 !important;margin: 0;width: 20px;height: 20px;margin-right: 5px;background: transparent url("~@/../static/img/fileType/folder/folder.svg")no-repeat center / contain;margin-left: 20px;& ~ span:not(.el-icon-loading) {width: 100%;.node-label {height: 40px;display: flex;align-items: center;}}&.expanded {flex-shrink: 0;transform: rotate(0deg);background-image: url("~@/../static/img/fileType/folder/folder-open.svg");}&.is-leaf {background-image: none;}}.normal-tree-node {margin-left: 10px;background-image: url("~@/../static/img/fileType/folder/arrow-right.svg");&.expanded {transform: rotate(90deg);background-image: url("~@/../static/img/fileType/folder/arrow-right.svg");}&.is-leaf {background-image: none;}}.plus-tree-node {margin-left: 10px;background-image: url("~@/../static/img/fileType/folder/plus.svg");&.expanded {background-image: url("~@/../static/img/fileType/folder/minus.svg");}&.is-leaf {background-image: none;}}// 隐藏一级节点的复选框&.hideRootNodeCheckbox > div > .el-tree-node__content .el-checkbox {display: none;}}}
}.tree-el-popover {.el-button {padding-top: 0;padding-bottom: 0;}
}
</style>
应用
<template><div :class="$options.name"><sgTreev-loading="loading":key="$route.query.BMID + sgTree_fresh":treeData="treeData":data="treeConfigData"@currentChange="currentChange"@addNode="addNode"@removeNode="removeNode":uploadData="{name: `file`,accept: '.xls,.xlsx',actionUrl: `${$d.API_ROOT_URL}/core/column/importColumn`, //批量导入树结构接口actionData: {BMID: $global.getBMID(),PID: `root`,sgLog: `强哥请求来源:${$options.name}导入栏目xls`,},}"@uploadSuccess="uploadSuccess"@uploadError="uploadError"@importError="importError"@downloadTpl="downloadTpl"draggable:allowNodeDrop="allowNodeDrop"@nodeDragEnd="nodeDragEnd"/></div>
</template><script>
import sgTree from "@/vue/components/admin/sgTree";
export default {name: "sgBody",components: {sgTree,},data() {return {sgTree_fresh: false,autoId: 0, //自增编号treeConfigData: {nodeKey: `ID`, //主键props: { label: "MC", isLeaf: "leaf" }, //配置选项iconType: "plus", //节点图标:folder文件夹|normal普通样式|plus加减符号样式text: {addRootButtonText: "添加根目录", //添加根节点按钮文本removeConfirmTitle: "警告!!!", //删除节点提示标题removeConfirmTip: "此操作将永久删除该节点及其下面的子节点,是否继续?", //删除节点提示内容},},treeData: [],loading: false,};},created() {this.initTreeData();},methods: {//初始化数据initTreeData({ d } = {}) {this.$global.获取整棵树的数据({cb: (d) => {this.treeData = d;},});},// 拖拽节点相关方法----------------------------------------allowNodeDrop(draggingNode, dropNode, dropType) {// 只允许拖拽同级别前后排序let isPrevOrNext = dropType === "prev" || dropType === "next";// 同在第一级根节点下let isSameRootLevel =draggingNode.level === dropNode.level && draggingNode.level === 1;// 同在一个节点(非根节点)下let isSameChildLevel =draggingNode.parent &&dropNode.parent &&draggingNode.parent.data &&dropNode.parent.data &&draggingNode.parent.data.ID === dropNode.parent.data.ID;return isPrevOrNext && (isSameRootLevel || isSameChildLevel);},nodeDragEnd(draggingNode, dropNode, dropType, ev) {// 只允许拖拽同级别前后排序let isBeforeOrAfter = dropType === "before" || dropType === "after";if (isBeforeOrAfter) {/* console.log("被拖拽的节点", draggingNode.data.MC, draggingNode.data.PXZ); console.log("停靠的节点", dropNode.data.MC, dropNode.data.PXZ); */let theSameLevelDatas = (dropNode.parent.childNodes || []).map((v) => v.data); // 获取同一级节点数据theSameLevelDatas.forEach((v, i) => (v.PXZ = i)); //重新排序// console.log("拖拽排序", theSameLevelDatas); //这里需要调用后台接口let IDS = theSameLevelDatas.map((v) => v.ID); //排序后的ID顺序数组let data = {IDS,sgLog: `强哥请求来源:${this.$options.name}更改同一层级树节点排序值`,};this.$d.修改节点排序({data,r: {s: (d) => {// console.log("【成功】", d);},},});}},// ----------------------------------------// 获取当前聚焦节点的数据currentChange(d) {console.log(``, d);},// 添加节点addNode({ data, resolve }) {this.$d.新增节点({data: {MC: `新增节点名称(${++this.autoId})`,},doing: {l: { show: () => (this.loading = true), close: () => (this.loading = false) },s: (d) => resolve(d),f: (d) => reject(d), //删除失败},});},// 删除节点removeNode({ node, data, resolve, reject }) {this.$d.删除节点({data: { ID: data.ID },doing: {s: (d) => resolve(d),f: (d) => reject(d), //删除失败},});},updateList(d) {},uploadSuccess(d, f) {this.sgTree_fresh = !this.sgTree_fresh;},uploadError(d, f) {this.$message.error(d.msg);},// 导入失败importError(d, f) {},// 下载导入模板downloadTpl(d) {},},
};
</script>
关联懒加载树节点组件【sgLazyTree】自定义组件:动态懒加载el-tree树节点数据,实现增删改、懒加载及局部数据刷新。_el-tree 动态刷新-CSDN博客文章浏览阅读464次。【代码】【sgLazyTree】自定义组件:动态懒加载el-tree节点数据,实现增删改。_el-tree 动态刷新https://blog.csdn.net/qq_37860634/article/details/132639389
相关文章:
【sgTree】自定义组件:加载el-tree树节点整棵树数据,实现增删改操作。
特性 可以自定义主键、配置选项支持预定义节点图标:folder文件夹|normal普通样式多个提示文本可以自定义支持动态接口增删改节点可以自定义根节点id可以设置最多允许添加的层级深度支持拖拽排序,排序过程还可以针对拖拽的节点深度进行自定义限制支持隐藏…...
vue2面试题:vue组件之间的通信方式有哪些?
vue2面试题:vue组件之间的通信方式有哪些? 回答思路:1.组件通信的目的-->2.组件通信的分类-->3.组件通信的方案1.组件通信的目的2.组件通信的分类3.组件通信的方案(1)通过props传递数据(2)…...

Pytorch神经网络模型nn.Sequential与nn.Linear
1、定义模型 对于标准深度学习模型,我们可以使用框架的预定义好的层。这使我们只需关注使用哪些层来构造模型,而不必关注层的实现细节。 我们首先定义一个模型变量net,它是一个Sequential类的实例。 Sequential类将多个层串联在一起。 当给…...
C++-gdb调试常用功能
文章目录 启动gdb运行程序设置断点运行控制查看源码查看信息查看变量线程相关 gdb调试常用功能如下,其中bin为要调试的程序,arg为参数 启动gdb 启动调试 gdb bin带参数启动 gdb --args bin arg1 arg2so预加载LD_PRELOAD/path/to/lib.so && gdb …...

快速上手的AI工具-文心一言辅助学习
前言 大家好晚上好,现在AI技术的发展,它已经渗透到我们生活的各个层面。对于普通人来说,理解并有效利用AI技术不仅能增强个人竞争力,还能在日常生活中带来便利。无论是提高工作效率,还是优化日常任务,AI工…...
Boost 适用 filesystem 库,statx 函数无法找到引用问题的解决方案。
1、boost 高版本使用了 statx 函数,这个函数是在 Linux 内核版本 4.11 之后引入的。 所以:可以升级 Linux 内核版本到4.11之后即可。 2、降低 boost 库版本到 1.70 以下 3、正确的路,改 boost 的编译代码 先看这个: Filesyste…...

MyBatis中一级缓存是什么?SqlSession一级缓存失效的原因?如何理解一级缓存?
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就 会从缓存中直接获取,不会从数据库重新访问 使一级缓存失效的四种情况: 1) 不同的SqlSession对应不同的一级缓存 2) 同一…...

项目解决方案:多地医馆的高清视频监控接入汇聚联网
目 录 一、背景 二、建设目标及需求 1.建设目标 2.现状分析 3.需求分析 三、方案设计 1.设计依据 2.设计原则 3.方案设计 3.1 方案描述 3.2 组网说明 四、产品介绍 1.视频监控综合资源管理平台介绍 2.视频录像服务器和存储 2.1概述 2.2存储设计 …...

【前端基础--2】
选择器优先级 style标签中: .text{color: pink;}div{color: red;}#box{color: skyblue;} body标签中: <div class"text" id"box">猜猜我是什么颜色的</div> 运行结果: 选择器优先级权重: id选…...

【GitHub项目推荐--提取文字】【转载】
提取视频中的字幕 这个开源项目是提取视频中字幕的开源项目,提取视频中的关键帧,检测视频帧中文本的所在位置,识别视频帧中文本的内容。 不知道大家有没有做笔记的习惯,这个开源项目就很方便的把你一个视频中的字幕提取出来&…...
WebSocket与Shiro认证信息传递的实现与安全性探讨
在现代Web应用程序中,WebSocket已经成为实时双向通信的重要组件。而Shiro作为一个强大的Java安全框架,用于处理身份验证、授权和会话管理。本文将探讨如何通过WebSocket与Shiro集成,实现认证信息的传递,并关注在这一过程中确保安全…...

QT 实现自动生成小学两位数加减法算式
小学生加减法训练 QT实现–自动生成两位数加减法算式,并输出txt文件 可以copy到word文件,设置适当字体大小和行间距,带回家给娃做做题 void MainWindow::test(int answerMax, int count) {// 创建一个随机数生成器QRandomGenerator *gener…...

小程序学习-20
建议每次构建npm之前都先删除miniprogram_npm...

面试题-【消息队列】
消息队列 问题1 如何进行消息队列的技术选型优点解耦 (pub/sub模型)异步(异步接口性能优化)削峰 使用消息队列的缺点几种消息队列的特性 问题2 引入消息队列之后该如何保证其高可用性RabbitMQ的高可用kafka高可用 问题3 在消息队列…...

【江科大】STM32:I2C通信外设(硬件)
在将2C通信外设之前,我们先捋一捋,串口的相关特点来和I2C进行一个对北比。 首先: 1,大部分单片机,设计的PCB板均带有串口通信的引脚(也就是通信基本都借助硬件收发器来实现) 2.对于串口的异步时序ÿ…...
【机器学习300问】15、什么是逻辑回归模型?
一、逻辑回归模型是为了解决什么问题? 逻辑回归(Logistic Regression)是一种广义线性回归分析模型,尤其适用于解决二分类问题(输出为两个类别)。 (1)二分类举例 邮件过滤ÿ…...

C#调用C动态链接库
前言 已经没写过博客好久了,上一篇还是1年半前写的LTE Gold序列学习笔记,因为工作是做通信协议的,然后因为大学时没好好学习专业课,现在理论还不扎实,不敢瞎写; 因为工作原因,经常需要分析一些字…...

前端实现转盘抽奖 - 使用 lucky-canvas 插件
目录 需求背景需求实现实现过程图片示意实现代码 页面效果lucky-canvas 插件官方文档 需求背景 要求实现转盘转动抽奖的功能: 只有正确率大于等于 80% 才可以进行抽奖;“谢谢参与”概率为 90%,“恭喜中奖”概率为 10%; 需求实现 实…...
2024.1.23力扣每日一题——最长交替子数组
2024.1.23 题目来源我的题解方法一 枚举 题目来源 力扣每日一题;题序:2765 我的题解 方法一 枚举 每次都以两个相邻作为满足要求的循环数据,并且以一个布尔变量控制循环的位置 时间复杂度:O(n) 空间复杂度:O(1) pub…...

C语言王道练习题第七周两题
第一题 Description 输入一个学生的学号,姓名,性别,用结构体存储,通过 scanf 读取后,然后再 通过 printf 打印输出 Input 学号,姓名,性别,例如输入 101 xiongda m Output 输出…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...