【sgTree】自定义组件:加载el-tree树节点整棵树数据,实现增删改操作。

news2024/11/19 4:38:05

特性 

  1. 可以自定义主键、配置选项
  2. 支持预定义节点图标:folder文件夹|normal普通样式
  3. 多个提示文本可以自定义
  4. 支持动态接口增删改节点
  5. 可以自定义根节点id
  6. 可以设置最多允许添加的层级深度
  7. 支持拖拽排序,排序过程还可以针对拖拽的节点深度进行自定义限制
  8. 支持隐藏一级节点(根节点)复选框☑
  9. 支持屏蔽一级节点(根节点)勾选☑

sgTree源码 

<template>
  <div :class="$options.name">
    <div class="tree-header" v-if="!(readonly || readonly === '')">
      <div class="sg-left">
        <template v-if="uploadData">
          <el-tooltip
            popper-class="sg-el-tooltip"
            :enterable="false"
            effect="dark"
            :content="`支持拖拽到树上传文件`"
            placement="top-start"
          >
            <el-button
              type="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-popover
          popper-class="tree-el-popover"
          placement="right"
          trigger="hover"
          title=""
          content=""
          :disabled="readonly || readonly === ''"
          slot-scope="{ node, data }"
        >
          <span class="right">
            <el-button
              title="添加"
              type="text"
              size=""
              icon="el-icon-circle-plus-outline"
              @click.stop="addNode(node, data)"
              v-if="showAddButton(node)"
              >添加</el-button
            >
            <el-button
              title="删除"
              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, //聚焦高亮新添加ID
      mainKey: "id", //默认主键
      defaultRootId: "root", //默认根节点ID就是root
      maxAddLevel: 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); //根节点ID
        d.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">
    <sgTree
      v-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

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

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

相关文章

Find My手套|苹果Find My技术与手套结合,智能防丢,全球定位

手套是手部保暖或劳动保护用品&#xff0c;也有装饰用的。手套是个很特别的东西&#xff0c;当初它的产生并不是为了实用&#xff0c;只是到近代&#xff0c;它才成了寒冷地区保温必备之物&#xff0c;或是医疗防菌、工业防护用品。手套按照制作方法分为缝制、针织、浸胶等。如…

Vue3 Suspense

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

Vite插件自动编译svg图标为字体

前言 今天来点儿6的.本文或许需要花费点时间才能理解. 目前是草稿阶段,比较凌乱,许多部分没有详细说明,日后有空更新补充. 本文主要提供解决思路,请按需调整. 很多时候我们在开发阶段是不能确定使用哪些图标的,它会随着开发不停的新增或调整. 所以我一般会从iconfont直接下载…

「Qt Widget中文示例指南」如何实现一个日历?(三)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 本文中的CalendarWi…

RabbitMQ中交换机的应用 ,原理 ,案例的实现

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是平顶山大师&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《RabbitMQ中交换机的应用及原理&#xff0c;案…

如何保证缓存与数据库双写时的数据一致性?

背景&#xff1a;使用到缓存&#xff0c;无论是本地内存做缓存还是使用 Redis 做缓存&#xff0c;那么就会存在数据同步的问题&#xff0c;因为配置信息缓存在内存中&#xff0c;而内存时无法感知到数据在数据库的修改。这样就会造成数据库中的数据与缓存中数据不一致的问题。 …

代码中遇到的问题2

目录 记录: 好处&#xff1a; 问题一&#xff1a; 解答: 问题二: 解答: 常见类型问题: 记录: string connStr ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; 在代码中写上这段代码&#xff0c;将连接数据库的代码语句放到&#xff…

安全基础~通用漏洞2

文章目录 知识补充盲注Boolean盲注延时盲注报错注入二次注入 知识补充 盲注常用 if(条件,5,0) #条件成立 返回5 反之 返回0 left(database(),1)&#xff0c;database() #left(a,b)从左侧截取a的前b位 盲注 盲注就是在注入过程中&#xff0c;获取的数据不能回显至前端页面。 …

Oracle Linux 7.9 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

Ask for Power Apps 消失了?

Ask for Power Apps 消失了? 背景替换定义一个接收数组的参数1.我们新建一个Text接收参数取名为**Arrlist**.定义一个参数类型是Array 背景 今天才发现&#xff0c;我在flow中想向power apps索要一个参数&#xff0c;但是之前的Ask for Power Apps 这个触发器怎么也找不到了。…

【Vulnhub通关】Kioptrix:Level 1 (#1)

文章目录 准备工作靶机基本信息下载 渗透流程主机发现目标扫描服务探测HTTP(S)服务SMB文件共享服务 权限提升本次靶机测试到此结束 注意&#xff1a;本文转载自本人稀土掘金博客。博客地址&#xff1a;御坂19008号 的个人主页 - 动态 - 掘金 准备工作 靶机基本信息 靶机名称&a…

SUSE Linux 15 SP5 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

寒假思维训练day12 E. Increasing Subsequences

适合喜欢算法、对算法感兴趣的朋友。 今天又来更新啦&#xff0c;断更一天&#xff0c;有点摆了&#xff0c;今天继续补上&#xff0c;献上一道1800的构造。 摘要&#xff1a; part1&#xff1a;关于一些构造题的总结 part2: 每日一题: Problem - E - Codeforces (链接在此…

【XR806开发板试用】通过MQTT实现手机远程实现PWM控灯

本文参与极术社区的《基于安谋科技STAR-MC1的XR806开发板试用》活动。 一、例程编译、烧录确认 首先按照全志在线文档平台的点灯教程确保能正常编译、烧录和点灯&#xff1a;https://xr806.docs.aw-ol.com/study/soft_led/ 确保例程没问题后&#xff0c;我们再改造例程&#xf…

Java入门高频考查基础知识5(扎实技术基础应变一切变化-45题4.2万字参考答案)

技术变革裁员影响的因素&#xff1a; 自动化替代简单重复性工作&#xff1a;随着技术的发展&#xff0c;一些简单、重复性的编码任务可能被自动化工具或者机器学习算法取代。这可能导致一些岗位的需求减少或者消失&#xff0c;从而可能导致部分人员裁员。 技能更新要求&#x…

怎么移除WordPress后台工具栏“新建”菜单?如何添加“新建文章”菜单?

默认情况下&#xff0c;WordPress后台顶部管理工具栏有左侧有一个“新建”菜单&#xff0c;而且还有下拉菜单文章、媒体、链接、页面和用户等&#xff0c;不过我们平时用得最多的就是“新建文章”&#xff0c;虽然可以直接点击“新建”&#xff0c;或点击“新建 – 文章”&…

Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

目录 AOP概念AOP底层原理AOP(JDK动态代理)使用 JDK 动态代理&#xff0c;使用 Proxy 类里面的方法创建代理对象**编写** **JDK** 动态代理代码 AOP(术语)AOP操作&#xff08;准备工作&#xff09;**AOP** **操作&#xff08;**AspectJ注解)**AOP** **操作&#xff08;**AspectJ…

c++ 包管理工具vcpkg

微软包管理工具 一、下载 git clone https://github.com/microsoft/vcpkg二、初始化 ./vcpkg/bootstrap-vcpkg.sh三、查看帮助文档 ./vcpkg/vcpkg help四、安装包 vcpkg/vcpkg install fmt五、查看安装包 vcpkg/vcpkg list输出 包实际安装路径 ./vcpkg/packages/fmt_x…

LoadRunner从零开始之走近LoadRunner

3.1 LoadRunner 的运行原理 安装LoadRunner 后&#xff0c;在菜单“开始” 一“MercuryLoadRunner” 中&#xff0c;你会看 到这样一组程序&#xff0c;如图 3-1 所示。 • 其中Applications 下面的Analysis、Controller 和Virtual User Generator 是我们 做性能测试最常用的…

大学生求职遇到在线测评 需要结合实际做吗

每年毕业季&#xff0c;都有大量的大学生求职&#xff0c;企业在这个时候往往能够收到很多的求职简历&#xff0c;尤其是一些比较好的岗位&#xff0c;原本只是想要招收10个人&#xff0c;但是结果光是简历就收到上千个简历&#xff0c;一个个面试不实际&#xff0c;浪费时间和…