vue2--基于zm-tree-org实现公司部门组织架构图

news2024/11/16 23:53:16

1.安装zm-tree-org

npm i zm-tree-org -S

2.引入使用

import Vue from 'vue';
import ZmTreeOrg from 'zm-tree-org';
import "zm-tree-org/lib/zm-tree-org.css";

Vue.use(ZmTreeOrg);

3.个人需求

组织架构图中:部门可拖动更改所属部门,可增加部门下节点,删除当前部门节点,查看当前部门节点的所有所属节点,编辑当前部门节点,同级部门节点可进行左右换位移动

4.实现效果

基于zm-tree-org实现组织架构图
整体如图所示:
在这里插入图片描述
因为需求没有用插件里面的自定义右键菜单(define-menus)
实现效果如图所示:
请添加图片描述

5.代码实现

<template>
  <div>
    <div
      id="mainContent"
      style="height: 800px; border:1px solid #eee"
    >
      <zm-tree-org
        ref="treeRefs"
        node-key="id"
        :data="data"
        :horizontal="horizontal"
        :collapsable="collapsable"
        :node-draggable="true"
        :only-one-node="onlyOneNode"
        :clone-node-drag="cloneNodeDrag"
        :tool-bar="toolBar"
        :default-expand-level="5"
        :define-menus="defineMenus"
        :node-delete="handleOnNodeDelete"
      >
       <!-- 利用插槽实现自定义节点 -->
        <template v-slot="{node}">
          <div class="card-main">
            <div :class="node.isRoot?'top-position top-position-root':'top-position'">
              <div
                v-if="!node.isRoot"
                @click="handleChangeNode($event,node,'before')"
              ><i class="el-icon-arrow-left" /></div>
              <div>{{ node.department }}</div>
              <div
                v-if="!node.isRoot"
                @click="handleChangeNode($event,node,'after')"
              ><i class="el-icon-arrow-right" /></div>
            </div>
            <!-- <div class="top-position">{{ node.department }}</div> -->
            <div class="p-title">{{ node.operation }}</div>
            <div class="p-people">
              <div class="p-peopleName">
                <div
                  v-if="node.name"
                  class="p-cicle"
                >{{ getNameCicle(node.name,node) }}</div>
                <template v-else>
                  <div class="p-cicle p-cicle-empty"><span>虚位</span><span>以待</span></div>
                </template>

                <div class="p-name">{{ node.name }}</div>
              </div>
            </div>
            <div :class="node.isRoot ? 'operation-btn operation-root-btn' :'operation-btn'">
              <div @click="onNodeHandleBtn('add',node)">
                <i class="iconfont icon-tianjia" />
              </div>
              <!-- root节点只支持添加 -->
              <template v-if="!node.isRoot">
                <el-popover
                  :ref="`popover-${node.id}`"
                  placement="bottom"
                  trigger="click"
                  :append-to-body="false"
                  :popper-options="{ boundariesElement: 'body', gpuAcceleration: false,}"
                  popper-class="customCont"
                >
                  <div class="customCont-main">
                    <div
                      class="customCont-main-close"
                      @click="closePopover(`popover-${node.id}`)"
                    >
                      <i class="el-icon-close" />
                    </div>
                    <div
                      v-if="node.children && node.children.length"
                      class="organization"
                    >
                      <div
                        v-for="(item,index) in node.children"
                        :key="index"
                        class="organization-list"
                      >
                        <div class="organization-list-top">{{ item.department }}</div>
                        <div class="organization-list-content">{{ item.name }}</div>
                      </div>
                    </div>
                    <div
                      v-else
                      class="organization organization-empty"
                    >
                      <div class="organization-empty-info">
                        暂无消息
                      </div>
                    </div>
                  </div>
                  <div slot="reference">
                    <i class="iconfont icon-zuzhijiagou" />
                  </div>
                </el-popover>
                <div @click="onNodeHandleBtn('edit',node)">
                  <i class="iconfont icon-bianjishuru-xianxing" />
                </div>
                <div @click="onNodeDeleteBtn(node)">
                  <i class="iconfont icon-shanchu" />
                </div>
              </template>
            </div>
          </div>
        </template>
      </zm-tree-org>
    </div>
    <el-dialog
      :title="dialogType==='add' ? '新增部门' :'编辑部门'"
      :visible.sync="dialogVisible"
      custom-class="custom-dialog"
      center
    >
      <el-input
        v-model="departmentName"
        autocomplete="off"
        placeholder="部门名称(50字内)"
      />
      <div
        slot="footer"
        class="dialog-footer"
      >
        <el-button
          type="primary"
          @click="handelDepartment"
        >保 存</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import {
  getParentNode,
  getBeforeBrotherNode,
  getAfterBrotherNode,
  changeBeforeNode,
  changeAfterNode,
  handleOnNodeDelete,
} from "./common";
export default {
  data() {
    return {
      toolBar: {
        scale: false,
      },
      data: {
        id: 1,
        department: "某某某死扣的公司",
        operation: "管理员",
        name: "哈哈哈哈",
        isRoot: true,
        children: [
          {
            id: 2,
            pid: 1,
            department: "产品研发部",
            operation: "研发主管",
            name: "张三",
            children: [
              {
                id: 3,
                pid: 2,
                department: "科技创新中心",
                operation: "研发-前端",
                name: "前端哈",
              },
            ],
          },
          {
            id: 4,
            pid: 1,
            department: "销售部",
            operation: "销售主管",
            name: "李四",
            children: [
              {
                id: 5,
                pid: 4,
                department: "销售一部",
                operation: "销售1",
                name: "李四1",
              },
              {
                id: 6,
                pid: 4,
                department: "销售二部",
                operation: "销售2",
                name: "李四2",
              },
            ],
          },
          {
            id: 7,
            pid: 1,
            department: "财务部",
            operation: "财务总监",
            name: "王二",
            children: [
              {
                id: 8,
                pid: 7,
                department: "销售一部",
                operation: "销售1",
                name: "李四1",
              },
              {
                id: 9,
                pid: 7,
                department: "销售二部",
                operation: "销售2",
                name: "李四2",
                children: [
                  {
                    id: 10,
                    pid: 9,
                    department: "销售一部",
                    operation: "销售1",
                    name: "李四1",
                  },
                  {
                    id: 11,
                    pid: 9,
                    department: "销售二部",
                    operation: "销售2",
                    name: "李四2",
                    children: [
                      {
                        id: 12,
                        pid: 11,
                        department: "销售一部",
                        operation: "销售1",
                        name: "李四1",
                      },
                      {
                        id: 13,
                        pid: 11,
                        department: "销售二部",
                        operation: "销售2",
                        name: "李四2",
                      },
                    ],
                  },
                ],
              },
            ],
          },
        ],
      },
      horizontal: false, // 是否横向
      collapsable: true, // 是否可展开收起
      onlyOneNode: false, // 是否仅拖动当前节点
      cloneNodeDrag: false, // 是否拷贝节点拖拽
      expandAll: true, //
      dialogVisible: false, // 弹框显隐
      dialogType: "", // 弹框类型
      departmentName: "", // 部门名称
      nodeTree: "", // 当前点击的nodeTree
    };
  },
  methods: {
    handleOnNodeDelete,
    // 隐藏左键菜单
    defineMenus() {
      return [];
    },

    // 截取名字
    getNameCicle(name, node) {
      const len = name && name.length;
      return name && len && name.slice(len - 2, len);
    },

    // 关闭组织架构
    closePopover(refs) {
      document.body.click();
    },

    // 增加/编辑部门节点
    onNodeHandleBtn(type, node) {
      this.dialogType = type;
      this.dialogVisible = true;
      this.nodeTree = node;
      if (type === "edit") {
        this.departmentName = node.department;
      }
    },

    // 弹框保存按钮
    handelDepartment() {
      // 添加
      if (this.dialogType === "add") {
        const params = {
          id: Math.ceil(Math.random() * 1000 + 100),
          pid: this.nodeTree.id,
          level: this.nodeTree.level || -1,
          operation: "职位",
          name: "",
          department: this.departmentName,
        };
        if (Array.isArray(this.nodeTree["children"])) {
          this.nodeTree["children"].push(params);
        } else {
          this.$set(this.nodeTree, "children", [].concat(params));
        }
        // 编辑
      } else {
        this.$set(this.nodeTree, "department", this.departmentName);
      }
      this.dialogVisible = false;
      this.departmentName = "";
    },

    // 删除部门节点
    onNodeDeleteBtn(node) {
      const _this = this;
      if (node.root) {
        // 根节点不允许删除
        this.$Message.warning("根节点不允许删除!");
        return false;
      }
      // 部门无职位信息
      const tips =
        node.children && node.children.length
          ? `<div>系统检测到该部门下仍有相关职位信息,请转移/删除对应职位后再试!</div>`
          : `<div>您确定要删除部门:<span style="color:#0469c0">${node.department}</span> 吗?</div>`;
      _this
        .$alert(tips, "提示", {
          dangerouslyUseHTMLString: true,
          customClass: "deleteDailog",
          showCancelButton: !(node.children && node.children.length),
          showConfirmButton: !(node.children && node.children.length),
          confirmButtonText: "确定",
          cancelButtonText: "取消",
        })
        .then(async () => {
          try {
            const parentNode = getParentNode(this.data, "id", node.pid);
            handleOnNodeDelete(this, node, parentNode);
          } catch (error) {
            _this.$message({
              type: "error",
              message: "操作失败,请重试!",
            });
          }
        })
        .catch(() => {});
    },

    // 同级部门交换节点
    handleChangeNode(e, node, type) {
      e.stopPropagation();
      const resultData = [].concat(this.data);
      if (type === "before") {
        // 判断是否有前面兄弟节点
        const isHasBeforNode = getBeforeBrotherNode(resultData, node, type);
        if (!isHasBeforNode?.id) {
          // 前面无兄弟节点
          return false;
        } else {
          // 有兄弟节点 进行交换处理
          const _data = Object.assign(
            {},
            { ...changeBeforeNode(resultData, isHasBeforNode, node) }
          )[0];
          this.$nextTick(() => {
            this.$set(
              this.data,
              "children",
              JSON.parse(JSON.stringify(_data.children))
            );
          });
          this.$message({
            message: "操作成功!",
            type: "success",
          });
        }
      } else {
        // 判断后面是否有兄弟节点
        const isHasAfterNode = getAfterBrotherNode(resultData, node, type);
        if (!isHasAfterNode?.id) {
          return false;
        } else {
          const _data = Object.assign(
            {},
            changeAfterNode(resultData, isHasAfterNode, node)
          )[0];
          this.$nextTick(() => {
            this.$set(
              this.data,
              "children",
              JSON.parse(JSON.stringify(_data.children))
            );
          });
          this.$message({
            message: "操作成功!",
            type: "success",
          });
        }
      }
    },
  },
};
</script>
<style lang="scss" scoped>
/* 每个节点样式 */
.card-main {
  min-width: 15vw;
  font-size: 12px;
  .top-position {
    background-color: #899cc1;
    color: #ffffff;
    padding: 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .top-position-root {
    justify-content: center;
  }
  .p-title {
    color: #868686;
    padding: 15px 0;
  }
  .p-people {
    display: flex;
    justify-content: space-evenly;
    .p-peopleName {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    .p-cicle {
      background: rgba(4, 45, 124, 0.5);
      color: #ffffff;
      border-radius: 42px 42px 42px 42px;
      width: 48px;
      height: 48px;
      line-height: 48px;
      font-size: 14px;
      margin-bottom: 5px;
    }
    .p-cicle-empty {
      display: flex;
      flex-direction: column;
      justify-content: center;
      line-height: 20px;
    }
    .p-name {
      color: #000000;
      min-height: 13.8px;
    }
  }

  .operation-btn {
    display: flex;
    justify-content: space-between;
    background: #f9f9f9;
    height: 40px;
    padding: 0 10px;
    align-items: center;
    margin-top: 15px;
    position: relative;
  }
  .operation-root-btn {
    justify-content: flex-end;
  }
}
/* 节点操作按钮 */
.iconfont {
  font-size: 20px;
  color: #878787;
}
/* popover样式 */
.operation-btn ::v-deep.customCont {
  background: #e2f4e9;
  margin-top: 15px;
  .popper__arrow::after {
    border-bottom-color: #e2f4e9;
  }
}
.customCont-main {
  position: relative;

  &-close {
    position: absolute;
    z-index: 10;
    top: -5px;
    right: 0;
    .el-icon-close:before {
      font-size: 16px;
      font-weight: 600;
    }
  }
}
.organization {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  padding: 0 18px 18px;
  min-width: 30vw;
}
.organization-list {
  font-size: 12px;
  min-height: 80px;
  border: 1px solid rgba(0, 0, 0, 0.06);
  margin-top: 18px;
  width: 45%;

  &-top {
    background: rgba(42, 178, 98, 0.88);
    color: #ffffff;
    padding: 10px;
    text-align: center;
  }
  &-content {
    padding: 20px;
    color: #000000;
    background: #ffffff;
  }
}
.organization-empty {
  min-width: 20vw;
  min-height: 50px;
  padding: 0;

  &-info {
    width: 100%;
    text-align: center;
    font-size: 12px;
    color: #000000;
  }
}
</style>
<style lang="scss">
/* 新增部门弹框 */
.custom-dialog {
  width: 18%;
  .el-dialog__header {
    border-bottom: 1px solid #e8e8e8;
    .el-dialog__title {
      font-size: 14px;
    }
    .el-dialog__headerbtn .el-dialog__close {
      font-weight: 600;
    }
  }
  .el-dialog__body {
    .el-input.is-active .el-input__inner,
    .el-input__inner:focus {
      border-color: #042d7c;
      outline: 0;
    }
  }

  .dialog-footer {
    text-align: center;
    .el-button {
      background: #042d7c;
      color: #ffffff;
    }
  }
  .error-tips {
    font-size: 12px;
    color: #f56c6c;
    line-height: 1;
    padding-top: 4px;
    position: absolute;
  }
}
.tree-org-node__inner:hover {
  box-shadow: 2px 2px 5px rgba(4, 45, 124, 0.55);
}
/* 删除部门弹框 */
.deleteDailog {
  min-width: 30vw;
  .el-message-box__header {
    border-bottom: 1px solid #e8e8e8;
  }
  .el-message-box__message {
    text-align: center;
  }

  /* .el-message-box__btns {
    .el-button:focus,
    .el-button:hover {
      color: #606266;
      border-color: #dcdfe6;
      background-color: #ffffff;
    }
    .el-button--primary {
      background-color: #042d7c;
      border-color: #042d7c;
    }
    .el-button--primary:focus,
    .el-button--primary:hover {
      background-color: #042d7c;
      color: #ffffff;
      border-color: #042d7c;
    }
  } */
}
</style>

common.js中的方法

// 递归查找父节点
/**
 *
 * @param {*} treeData 整个组织架构数据
 * @param {*} key id键值名
 * @param {*} pid 父节点id
 * @returns
 */
export const getParentNode = (treeData, key, pid) => {
  if (treeData[key] === pid) {
    return treeData;
  } else if (Array.isArray(treeData.children)) {
    const list = treeData.children;
    for (let i = 0, len = list.length; i < len; i++) {
      const row = list[i];
      const pNode = getParentNode(row, key, pid);
      if (pNode) {
        return pNode;
      }
    }
  }
}

// 查找前面兄弟节点
/**
 *
 * @param {*} treeData 整个组织架构数据
 * @param {*} nowNode 当前节点
 * @returns
 */
export const getBeforeBrotherNode = (treeData, nowNode) => {
  for (let i = 0, len = treeData.length; i < len; i++) {
    if (treeData[i].id === nowNode.id) {
      if (i > 0) {
        return treeData[i - 1];
      } else {
        // 没有前面兄弟节点
        return false;
      }
    } else if (treeData[i].children) {
      const isHasBeforNode = getBeforeBrotherNode(treeData[i].children, nowNode);
      if (isHasBeforNode) return isHasBeforNode;
    }
  }
}

// 和前面兄弟节点进行交换
/**
 *
 * @param {*} treeData 整个组织架构数据
 * @param {*} beforeNode 前兄弟节点
 * @param {*} nowNode 当前节点
 * @returns
 */
export const changeBeforeNode = (treeData, beforeNode, nowNode) => {
  for (let i = 0, len = treeData.length; i < len; i++) {
    if (treeData[i].id === nowNode.id) {
      let obj = {};
      obj = treeData[i];
      treeData[i] = beforeNode;
      treeData[i - 1] = nowNode;
      break;
    } else if (treeData[i].children) {
      changeBeforeNode(treeData[i].children, beforeNode, nowNode);
    }
  }
  return treeData;
}

// 查找后面的兄弟节点
/**
 *
 */
export const getAfterBrotherNode = (treeData, nowNode) => {
  for (let i = 0, len = treeData.length; i < len; i++) {
    if (treeData[i].id === nowNode.id) {
      if (i < treeData.length - 1) {
        return treeData[i + 1];
      } else {
        // 没有后面兄弟节点
        return false;
      }
    } else if (treeData[i].children) {
      const isHasAfterNode = getAfterBrotherNode(
        treeData[i].children,
        nowNode
      );
      if (isHasAfterNode) return isHasAfterNode;
    }
  }
}

// 和后面兄弟节点进行交换
/**
 *
 * @param {*} treeData 整个组织架构数据
 * @param {*} beforeNode 后兄弟节点
 * @param {*} nowNode 当前节点
 * @returns
 */
export const changeAfterNode = (treeData, afterNode, nowNode) => {
  for (let i = 0, len = treeData.length; i < len; i++) {
    if (treeData[i].id === nowNode.id) {
      let obj = {};
      obj = treeData[i];
      treeData[i] = afterNode;
      treeData[i + 1] = nowNode;
      break;
    } else if (treeData[i].children) {
      changeAfterNode(treeData[i].children, afterNode, nowNode);
    }
  }
  return treeData;
}

// 处理删除节点(调用原组件事件)
/**
 *
 * @param {*} nowNode  当前节点
 * @param {*} parentNode 父节点
 */
export const handleOnNodeDelete = (_, nowNode, parentNode) => {
  const list = parentNode["children"];
  for (let i = 0, len = list.length; i < len; i++) {
    if (list[i]["id"] === nowNode["id"]) {
      list.splice(i, 1);
      _.$emit("on-node-delete", nowNode, parentNode);
      break;
    }
  }
}

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

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

相关文章

javascript学习+Vue学习+项目开发

一 《学习JavaScript数据结构与算法》 1.ES2015的类是基于原型语法的语法糖 2.TypeScript是一个开源的、渐进式包含类型的JavaScript超集 以&#xff0e;ts为扩展名 以tsc命令来编译它 TypeScript允许我们给变量设置一个类型&#xff0c;不过写法太啰唆了。 TypeScript有一…

博客系统——项目测试报告

目录 前言 博客系统——项目介绍 1、测试计划 1.1、功能测试 1.1.1、编写测试用例 1.1.2、实际执行步骤 1.2、使用Selenium进行Web自动化测试 1.2.1、引入依赖 1.2.2、提取共性&#xff0c;实现代码复用 1.2.3、创建测试套件类 1.2.4、博客登录页自动化测试 1.2.5、…

SQL注入报错注入之floor()报错注入原理分析

简介 对于SQL注入的报错注入通常有三个函数需要我们掌握&#xff1a; extractValue(xml_frag, xpath_expr)updateXML(xml_target, xpath_expr,new_xml)floor() 对于extractValue和updateXML函数来说比较好理解&#xff0c;就不做解释了&#xff0c;这里只对floor函数的报错注…

LabVIEW网络服务安全2

LabVIEW网络服务安全2在客户端应用程序中创建签名对请求进行签名要求您具有能够从客户端的编程语言调用的MD5摘要算法以及SHA256加密摘要算法的实现。这两种算法通常都可用于大多数平台。还需要&#xff1a;1. 要使用的HTTP方法的字符串&#xff08;“GET”、“POST”、“PUT”…

收发器上的10G网络变压器有什么特殊要求?

Hqst盈盛电子导读&#xff1a;那么&#xff0c;为了保证我们购买到正常的真正的具备POE功能的10G网络变压器&#xff0c;我们又要如何做呢以及如何判断呢&#xff1f;随着高速以太网网络传速的快速发展&#xff0c;10G以太网&#xff0c;10G网络变压器滤波器在各个领域也得到了…

基于SpringCloud的可靠消息最终一致性05:保存并发送事务消息

在有了分布式事务的解决方案、项目的需求、骨架代码和基础代码,做好了所有的准备工作之后,接下来就可以继续深入了解「核心业务」了。 在前面了解分布式事务时,可靠消息最终一致性方案的流程图是这样的: 图三十一:可靠消息最终一致性 整个的流程是: 1、业务处理服务在事务…

GLSL shader学习系列1-Hello World

这是GLSL shader系列第一篇文章&#xff0c;本文学习目标&#xff1a; 安装编辑工具编写hello world程序 安装插件 我使用VSCode编写shader代码&#xff0c;在VSCode上有两个好用的插件需要先装一下&#xff1a; Shader languages support for VS Code glsl-canvas&#xf…

优维科技实力入选《2023深圳金融业信息技术融合创新案例汇编》

日前&#xff0c;由深圳市金融科技协会编制的《2023深圳金融业信息技术融合创新案例汇编》于“2022中国&#xff08;深圳&#xff09;金融科技全球峰会”正式对外发布&#xff0c;共汇编近90个优秀金融技术应用实践案例&#xff0c;优维科技凭借在“某银行自动化运维XC改造项目…

STM32——毕设智能感应窗户

智能感应窗户 一、功能设计 以STM32F103芯片最小系统作为主控&#xff0c;实现自动监测、阈值设定功能和手动控制功能。 1、自动监测模式下&#xff1a; ① 采用温湿度传感器&#xff0c;实现采集当前环境的温度、湿度数值。 ② 采用光敏传感器&#xff0c;实现判断当前的环境…

【数据库/MySQL】MySQL三大日志提要

MySQL三大日志 mysql常用日志 错误日志查询日志慢查询日志事务日志【redo log&#xff08;重做日志&#xff09;、undo log&#xff08;回滚日志&#xff09;】二进制日志【bin log】 MySQL日志中比较重要的包括redo log&#xff08;重做日志&#xff09;、binlog&#xff0…

Docker 网络详解

前置网络知识 OSI七层网络模型 从下到上依次为&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 交换机&#xff1a;处在第二次&#xff0c;也就是数据链路层。作用&#xff1a;通过一个或者多个设备将不同子网连接在一起&#xff0c;相互通信&am…

Ant Design Vue 如何添加时间选择框

第一步引入 组件 import JDate from /components/jeecg/JDate使用 重点代码 <j-date<a-col :span"24/2"><a-form-item :labelCol"labelCol" :wrapperCol"wrapperCol" label"验收日期"><j-date placeholder"…

Lesson9---回归问题

9.1 机器学习基础 课程回顾 Python语言基础Numpy/Matplotlib/Pandas/Pillow应用TensorFlow2.0 低阶API 即将学习 机器学习、人工神经网络、深度学习、卷积神经网络典型模型的TensorFlow2.0实现 9.1.1 机器学习 机器学习&#xff08;Machine Learning&#xff09;&#xf…

2023年湖北七大员证书查询网站是哪里?

一、湖北七大员是哪七大员&#xff1f; 湖北七大员分别是&#xff1a;施工员、质量员、资料员、材料员、标准员、劳务员和机械员。其中施工员和质量员分为&#xff1a;市政、土建、装饰装修和设备安装四个子专业&#xff0c;其他不分。 二、湖北七大员证书查询网站是哪里&#…

Node下载阿里OSS存储文件【不知目录结构】

前言&#xff1a;前端传模型ID&#xff0c;后台根据ID去阿里OSS存储下载对应文件&#xff08;不知文件内部层级结构&#xff0c;且OSS只能单个文件下载&#xff09;&#xff0c;打包成zip字节流形式返回给前端下载。 需求分析&#xff1a; 生成OSS文件关系树Node做文件下载存…

ClickHouse 相关面试题

文章目录什么是 ClickHouse&#xff0c;它的特点是什么&#xff1f;ClickHouse的数据存储方式是什么&#xff0c;它与传统的行式存储有什么区别&#xff1f;ClickHouse 引擎ClickHouse的数据模型是什么&#xff0c;它与传统的关系型数据库的数据模型有什么区别&#xff1f;Clic…

【TVM 学习资料】TensorIR 快速入门

本篇文章译自英文文档 Blitz Course to TensorIR 作者是 Siyuan Feng。更多 TVM 中文文档可访问→TVM 中文站 TensorIR 是深度学习领域的特定语言&#xff0c;主要有两个作用&#xff1a; 在各种硬件后端转换和优化程序。自动 tensorized 程序优化的抽象。 import tvm from…

kafka(一) 的架构,各概念

Kafka架构 Kafak 总体架构图中包含多个概念&#xff1a; &#xff08;1&#xff09;ZooKeeper&#xff1a;Zookeeper负责保存broker集群元数据&#xff0c;并对控制器进行选举等操作。 &#xff08;2&#xff09;Producer&#xff1a; 生产者负责创建消息&#xff0c;将消息发…

Kafka 概述

文章目录Kafka定义消息队列消息队列应用场景缓冲/消峰 场景解耦 场景异步通信 场景消息队列两种模式点对点模式发布/订阅模式 ***kafka基础架构Kafka定义 消息队列 目前企业中比较常见的消息队列产品主要有 Kafka、ActiveMQ 、RabbitMQ 、RocketMQ 等。在大数据场景主要采用 Ka…

I.MX6ULL内核开发11:使用设备树实现RGB灯驱动

目录 一、实验说明 二、硬件原理图分析 2.1 打开原理图&#xff0c;找到rgb部分 2.2 对RGB的R灯进行寄存器设置 2.2.1 时钟配置 2.2.2 引脚复用GPIO 2.2.3 引脚属性设置 2.2.4 输出电平设置 三、实验代码 3.1 编程思路 3.2 代码分析 3.2.1 添加RGB设备节点 3.2.2 编…