Vue实现流程图,借鉴vue-tree-color 实现流程框架技术

news2024/11/29 22:38:40

Vue实现流程图,借鉴vue-tree-color 实现流程框架技术

文章目录

  • Vue实现流程图,借鉴vue-tree-color 实现流程框架技术
    • 借鉴鸣谢
    • 演示效果
    • 引入依赖
    • 添加全局
    • 组件的二次封装
      • 步骤1 创建组件目录
        • Vue
        • node.js
        • tree.less
    • 使用
      • 组件引入使用
      • 数据结构案例

借鉴鸣谢

实现组织架构图(vue-org-tree)
如果向使用原来的依赖可以使用这个人的,因为我也是根据这个博客大佬仿照Vue-org-tree实现的方案
对此有几点不惑,问了大佬,大佬也没有回复我

  • className 貌似不起作用,看了文章底部,她也意识到这个问题,但是没有给出详细的解决方案
  • node.js中虽然做了充分的注释,但是她把子节点渲染和主节点渲染给单独分开了,指定了render函数去渲染

演示效果

在这里插入图片描述
由于还在启动项目中,还没有完善,目前已经可以支持动态创建节点了
在这里插入图片描述
这是通过点击实现抽屉展示
在这里插入图片描述
这是通过hover鼠标悬停高亮,由于我并不是一个正儿八经的前端,准确的说我是来搞笑的。所以对于每个节点面板渲染是很简陋的。

引入依赖

# 这里是安装大佬提供的依赖
npm install vue-tree-color

检查less和less-loader,因为该组件使用到了less,可以看看项目工程是否已经安装

npm install --save-dev less less-loader

注意这里可能会在项目启动的时候出现以下问题

报错信息:Syntax Error: TypeError: this.getOptions is not a function

解决方案-需要在安装less和lessloader时,指定版本号,否则就会导致兼容问题。

npm i less@3.9.0 less-loader@4.1.0 -D

添加全局

找到main.js中追加一下内容

import Vue2OrgTree from 'vue-tree-color'
Vue.use(Vue2OrgTree)

组件的二次封装

在公共层面@components 目录下,我们需要进行二次封装,为什么要二次封装,上面已经说到原因了,因为定制化内容不同, 肯定会涉及更改组件渲染方式以及样式,因为二次封装是非常有必要的
在这里插入图片描述

步骤1 创建组件目录

我就随便给取了一个名字 SimpleTree 目录

Vue

组件页面,我没做更改,直接拿来用

<template>
  <div class="org-tree-container">
    <div class="org-tree" :class="{horizontal, collapsable}">
      <org-tree-node
        :data="data"
        :props="props"
        :judge="judge"
        :NodeClass="NodeClass"
        :horizontal="horizontal"
        :label-width="labelWidth"
        :collapsable="collapsable"
        :render-content="renderContent"
        :label-class-name="labelClassName"
        @on-expand="(e, data) => $emit('on-expand', e, data)"
        @on-node-focus="(e, data) => $emit('on-node-focus', e, data)"
        @on-node-click="(e, data) => $emit('on-node-click', e, data)"
        @on-node-mouseover="(e, data) => $emit('on-node-mouseover', e, data)"
        @on-node-mouseout="(e, data) => $emit('on-node-mouseout', e, data)"
      />
    </div>
  </div>
</template>
<!--
data:就是数据格式,时一个对象,具体格式下面有示例
horizontal:默认是false,即纵向展示
label-class-name:可以给节点添加的类名,不过我这边使用了没有效果,下面有其他方法来处理节点样式
collapsable:是否折叠,有这个属性,则表示默认折叠,有其他方法可以在存在此属性时,也保证是展开状态
on-expand:点击折叠点,点击可以展开,再次点击可以折叠,是个方法
on-node-click:顾名思义,就是点击节点,触发的事件
on-node-mouseover:鼠标移入节点触发的事件,可以触发一个弹层用于展示详情
on-node-mouseout:鼠标移出节点触发的事件,可以控制详情弹层的隐藏
-->
<script>
import render from './node'

export default {
  name: "SimpleTree",
  components: {
    OrgTreeNode: {
      render,
      functional: true
    }
  },
  props: {
    data: {
      type: Object,
      required: true
    },
    props: {
      type: Object,
      default: () => ({
        id: 'id',
        logo: 'logo',
        key: 'key',
        parentKey: 'parentKey',
        label: 'label',
        expand: 'expand',
        children: 'children',
        type: 'type',
        status: 'status',
        controller: 'controller',
        sys: 'sys',
        remark: 'remark',
        description: 'description',
        registration: 'registration'
      })
    },
    judge: {
      type: Object,
      required: false
    },
    NodeClass: {
      type: Array,
      required: false
    },
    horizontal: Boolean,
    selectedKey: String,
    collapsable: Boolean,
    renderContent: Function,
    labelWidth: [String, Number],
    labelClassName: [Function, String],
    selectedClassName: [Function, String]
  }
}
</script>

<style lang="less">
@import './tree';
</style>

node.js

这个js就是组件渲染的函数,可以稍微研究一下

// 判断是否叶子节点
const isLeaf = (data, prop) => {
  return !(Array.isArray(data[prop]) && data[prop].length > 0)
}
// 创建 node 节点
export const renderNode = (h, data, context) => {
  const { props } = context
  const cls = ['org-tree-node']
  const childNodes = []
  const children = data[props.props.children]

  if (isLeaf(data, props.props.children)) {
    cls.push('is-leaf')
  } else if (props.collapsable && !data[props.props.expand]) {
    cls.push('collapsed')
  }

  if (data) {
    childNodes.push(renderLabel(h, data, context))
  }

  if ((!props.collapsable || data[props.props.expand]) && children.length > 0) {
    childNodes.push(renderChildren(h, children, context))
  }

  return h('div', {
    domProps: {
      className: cls.join(' ')
    }
  }, childNodes)
}

// 创建展开折叠按钮
export const renderBtn = (h, data, { props, listeners }) => {
  const expandHandler = listeners['on-expand']

  let cls = ['org-tree-node-btn']

  if (data[props.props.expand]) {
    cls.push('expanded')
  }

  return h('span', {
    domProps: {
      className: cls.join(' ')
    },
    on: {
      click: e => expandHandler && expandHandler(e,data)
    }
  })
}

// 创建 label 节点
export const renderLabel = (h, data, context) => {
  const { props, listeners } = context
  const label = data[props.props.label]
  const renderContent = props.renderContent

  // event handlers
  const clickHandler = listeners['on-node-click']
  const mouseOverHandler = listeners['on-node-mouseover']
  const mouseOutHandler = listeners['on-node-mouseout']

  const childNodes = []
  if (typeof renderContent === 'function') {
    let vnode = renderContent(h, data)

    vnode && childNodes.push(vnode)
  } else {
    childNodes.push(label)
  }

  if (props.collapsable && !isLeaf(data, props.props.children)) {
    childNodes.push(renderBtn(h, data, context))
  }

  const cls = ['org-tree-node-label-inner']
  let { labelWidth, labelClassName, selectedClassName, selectedKey ,judge,NodeClass} = props

  if (typeof labelWidth === 'number') {
    labelWidth += 'px'
  }

  if (typeof labelClassName === 'function') {
    labelClassName = labelClassName(data)
  }

  labelClassName && cls.push(labelClassName)

  // add selected class and key from props
  if (typeof selectedClassName === 'function') {
    selectedClassName = selectedClassName(data)
  }

  selectedClassName && selectedKey && data[selectedKey] && cls.push(selectedClassName)

  return h('div', {
    domProps: {
      className: 'org-tree-node-label'
    }
  }, [h('div', {
    domProps: {
      className:ChangeTheColor(data,judge,NodeClass) + " org-tree-node-label-inner"
    },
    style: { width: labelWidth },
    on: {
      'click': e => clickHandler && clickHandler(e, data),
      'mouseover': e => mouseOverHandler && mouseOverHandler(e, data),
      'mouseout': e => mouseOutHandler && mouseOutHandler(e, data)
    }
  }, childNodes)])
}

function ChangeTheColor(e,judge,NodeClass){
  if(judge !== "" && judge !== undefined && judge !== null && judge.swtich !== false){
    for(var k in judge) {
      var a = (eval("e."+k))
      if(NodeClass){
        for(let c =0 ;c<NodeClass.length;c++){
          if( a === NodeClass[c])
            return  NodeClass[c]
          else if(NodeClass.length-1==c)
            return ""
        }
      }else{
        return ""
      }
    }
  }else{
    return ""
  }
}
// 创建 node 子节点
export const renderChildren = (h, list, context) => {
  if (Array.isArray(list) && list.length > 0) {
    const children = list.map(item => {
      return renderNode(h, item, context)
    })

    return h('div', {
      domProps: {
        className: 'org-tree-node-children'
      }
    }, children)
  }
  return ''
}

export const render = (h, context) => {
  const {props} = context
  if (props.data.id) {
    return renderNode(h, props.data, context)
  } else {
    return ''
  }

}

export default render

tree.less

.org-tree-container {
  display: inline-block;
  padding: 15px;
  background-color: #fff;
}

.org-tree {
  // display: inline-block;
  display: table;
  text-align: center;

  &:before, &:after {
    content: '';
    display: table;
  }

  &:after {
    clear: both;
  }
}

.org-tree-node,
.org-tree-node-children {
  position: relative;
  margin: 0;
  padding: 0;
  list-style-type: none;

  &:before, &:after {
    transition: all .35s;
  }
}
.org-tree-node-label {
  position: relative;
  display: inline-block;

  .org-tree-node-label-inner {
    padding: 10px 15px;
    text-align: center;
    border-radius: 5px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
    -webkit-transition-duration: 0.3s;
    transition-duration: 0.3s;
    cursor: pointer;
  }
  .org-tree-node-label-inner:hover {
    background-color: #c6e2ff;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1)
  }

}

.render-node-panel-header {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  margin: 10px 0;
}
.node-box {
  min-width: 200px;
}

.render-node-panel-middle {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: center;
}

.org-tree-node-btn {
  position: absolute;
  top: 100%;
  left: 50%;
  width: 20px;
  height: 20px;
  z-index: 10;
  margin-left: -11px;
  margin-top: 9px;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 50%;
  box-shadow: 0 0 2px rgba(0, 0, 0, .15);
  cursor: pointer;
  transition: all .35s ease;

  &:hover {
    background-color: #e7e8e9;
    transform: scale(1.15);
  }

  &:before, &:after {
    content: '';
    position: absolute;
  }

  &:before {
    top: 50%;
    left: 4px;
    right: 4px;
    height: 0;
    border-top: 1px solid #ccc;
  }

  &:after {
    top: 4px;
    left: 50%;
    bottom: 4px;
    width: 0;
    border-left: 1px solid #ccc;
  }

  &.expanded:after {
    border: none;
  }
}
.org-tree-node {
  padding-top: 20px;
  display: table-cell;
  vertical-align: top;

  &.is-leaf, &.collapsed {
    padding-left: 10px;
    padding-right: 10px;
  }

  &:before, &:after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 50%;
    height: 19px;
  }

  &:after {
    left: 50%;
    border-left: 1px solid #ddd;
  }

  &:not(:first-child):before,
  &:not(:last-child):after {
    border-top: 1px solid #ddd;
  }

}
.collapsable .org-tree-node.collapsed {
  padding-bottom: 30px;

  .org-tree-node-label:after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    width: 50%;
    height: 20px;
    border-right: 1px solid #ddd;
  }
}
.org-tree > .org-tree-node {
  padding-top: 0;

  &:after {
    border-left: 0;
  }
}
.org-tree-node-children {
  padding-top: 20px;
  display: table;

  &:before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    width: 0;
    height: 20px;
    border-left: 1px solid #ddd;
  }

  &:after {
    content: '';
    display: table;
    clear: both;
  }
}

.horizontal {
  .org-tree-node {
    // display: flex;
    // flex-direction: row;
    // justify-content: flex-start;
    // align-items: center;
    display: table-cell;
    float: none;
    padding-top: 0;
    padding-left: 20px;

    &.is-leaf, &.collapsed {
      padding-top: 10px;
      padding-bottom: 10px;
    }

    &:before, &:after {
      width: 19px;
      height: 50%;
    }

    &:after {
      top: 50%;
      left: 0;
      border-left: 0;
    }

    &:only-child:before {
      top: 1px;
      border-bottom: 1px solid #ddd;
    }

    &:not(:first-child):before,
    &:not(:last-child):after {
      border-top: 0;
      border-left: 1px solid #ddd;
    }

    &:not(:only-child):after {
      border-top: 1px solid #ddd;
    }

    .org-tree-node-inner {
      display: table;
    }

  }

  .org-tree-node-label {
    display: table-cell;
    vertical-align: middle;
  }

  &.collapsable .org-tree-node.collapsed {
    padding-right: 30px;

    .org-tree-node-label:after {
      top: 0;
      left: 100%;
      width: 20px;
      height: 50%;
      border-right: 0;
      border-bottom: 1px solid #ddd;
    }
  }

  .org-tree-node-btn {
    top: 50%;
    left: 100%;
    margin-top: -11px;
    margin-left: 9px;
  }

  & > .org-tree-node:only-child:before {
    border-bottom: 0;
  }

  .org-tree-node-children {
    // display: flex;
    // flex-direction: column;
    // justify-content: center;
    // align-items: flex-start;
    display: table-cell;
    padding-top: 0;
    padding-left: 20px;

    &:before {
      top: 50%;
      left: 0;
      width: 20px;
      height: 0;
      border-left: 0;
      border-top: 1px solid #ddd;
    }

    &:after {
      display: none;
    }

    & > .org-tree-node {
      display: block;
    }
  }
}

使用

组件引入使用

 <simple-tree
        :data="orgData"
        :horizontal="horizontalRadio"
        :label-class-name="labelClassName"
        :collapsable="collapsableRadio"
        @on-expand="onExpand"
        @on-node-click="NodeClick"
        @on-node-mouseover="onMouseover"
        @on-node-mouseout="onMouseout"
        :renderContent="renderContent"/>
  • 参数说明:
data: 就是树形结构,下面会有案例
horizontal:排列形式
collapsable: 是否展开
  • 函数说明:
on-expand: 展开、闭合节点
on-node-click: 节点点击事件
on-node-mouseover:鼠标悬停
on-node-mouseout:鼠标悬出
renderContent:渲染函数

数据结构案例

data(){
	return{
	  labelClassName: "bg-color-orange", // 看到node.js 中这个实际没用的
      basicInfo: { id: null, label: null },
      basicSwitch: false,
      data: {
        id: 0,
        label: "XXX科技有限公司",
        className: 'nxnnxnxn', // 切记HTML的class 标签属性不能以数字开头
        children: [
          {
            id: 2,
            label: "产品研发部",
            className: 'nxnnxnxn-1',
            children: [
              {
                id: 5,
                label: "研发-前端",
                children: [
                  {
                    id: 55,
                    className: 'nxnnxnxn-55',
                    label: "前端1"
                  },
                  {
                    id: 56,
                     className: 'nxnnxnxn-56',
                    label: "前端2"
                  },
                  {
                    id: 57,
                    className: 'nxnnxnxn-57',
                    label: "前端3"
                  },
                  {
                    id: 58,
                     className: 'nxnnxnxn-58',
                    label: "前端4"
                  }
                ]
              }
            ]
          }
        ]
      },
	}
},
methods:{
	//渲染节点
	renderContent(h, data) {
	// 通过data中的className属性来对div元素进行注入class
	// 每个节点渲染必然会走这个函数
	//这里对应的不同的className 需要在上面的tree.less中写入样式
      return (
        <div class = {data.className}>
          <div>
            <i class="el-icon-user-solid"></i>
            <span>{data.label}</span>
            <span></span>
          </div>
          <div style="font-size:12px;line-height:20px;">测试人员</div>
        </div>
      );
    },
    //鼠标移出
    onMouseout(e, data) {
       console.log("onMouseout", data)
    },
    //鼠标移入
    onMouseover(e, data) {
     console.log("onMouseover", data)
    },
    //点击节点
    NodeClick(e, data) {
      console.log(e, data);
    },
    //默认展开
    toggleExpand(data, val) {
      if (Array.isArray(data)) {
        data.forEach(item => {
          this.$set(item, "expand", val);
          if (item.children) {
            this.toggleExpand(item.children, val);
          }
        });
      } else {
        this.$set(data, "expand", val);
        if (data.children) {
          this.toggleExpand(data.children, val);
        }
      }
    },
    collapse(list) {
      list.forEach(child => {
        if (child.expand) {
          child.expand = false;
        }
        child.children && this.collapse(child.children);
      });
    },
    //展开
    onExpand(e, data) {
      if ("expand" in data) {
        data.expand = !data.expand;
        if (!data.expand && data.children) {
          this.collapse(data.children);
        }
      } else {
        this.$set(data, "expand", true);
      }
    },
}

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

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

相关文章

[附源码]Python计算机毕业设计Django的桌游信息管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

元宇宙产业委调研行杭州站 | 联合西溪谷管委会共商元宇宙赋能实体经济

11月29日下午&#xff0c;由杭州西溪谷建设发展管理委员会和中国移动通信联合会元宇宙产业工作委员会共同举办的“元宇宙赋能实体经济企业家沙龙暨元宇宙产业委调研行杭州站”在西溪谷杭州蚂蚁链产业创新中心召开。20余家元宇宙和区块链企业到场&#xff0c;西溪谷管委会党委书…

pytorch复习笔记--loss.backward()、optimizer.step()和optimizer.zero_grad()的用法

目录 1--loss.backward()的用法 2--optimizer.step()的用法 3--optimizer.zero_grad()的用法 4--举例说明 5--参考 1--loss.backward()的用法 作用&#xff1a;将损失loss向输入测进行反向传播&#xff1b;这一步会计算所有变量x的梯度值 &#xff0c;并将其累积为 进行备…

迎合国家新政策,共享购联合共享经济,三方互利,消费增值

共享单车打通出行“最后一公里”&#xff0c;共享充电宝让人们出门在外免于“电量烦恼”&#xff0c;共享办公降低办公成本……共享经济已深入到人们日常生活。近日&#xff0c;国家信息中心发布的《中国共享经济发展报告&#xff08;2022&#xff09;》显示&#xff0c;2021年…

EMR-Jindo Spark 核心引擎优化

Jindo-Spark 是阿里云智能E-MapReduce 团队在开源的Apache Spark 基础上自主研发的分布式云原生 OLAP 引擎&#xff0c;已经在近千E-MapReduce 客户中大规模部署使用。Jindo Spark 在开源版本基础上做了大量优化和扩展&#xff0c;深度集成和连接了众多阿里云基础服务。凭借该引…

工作流-流程实例【ProcessInstance】与执行实例【Execution】

一、ProcessInstance与Execution的区别 这是一个Activiti的难点&#xff0c;能够懂得这个&#xff0c;工作流也就入门大半了。 下面&#xff0c;我就细致的讲解一下他们的区别。 &#xff08;1&#xff09;首先&#xff0c;我们来看一张我总结的图片&#xff08;这个图片中两条…

Flink-处理函数以及TopN运用案例

7 处理函数 7.1 概述 更底层的操作&#xff0c;直接对流进行操作&#xff0c;直接调用处理函数 7.2 基本处理函数ProcessFunction 分析 ProcessFunction的来源 处理函数继承了AbstractRichFunction富函数抽象类&#xff0c;因此就具有访问状态(state)和其他运行时环境 例…

Day39——Dp专题

文章目录01背包二维数组一维数组6.整数拆分7.不同的二叉搜索01背包 01背包&#xff1a;每一个物品只能选一次&#xff0c;选或者不选 状态标识&#xff1a;f[i][j]&#xff1a;所有只考虑前i个物品&#xff0c;且总体积不超j的所有选法的集合 属性&#xff1a;Max 状态计算&a…

链表之反转链表

文章目录链表之反转链表题目描述解题思路代码实现链表之反转链表 力扣链接 题目描述 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。 示例&#xff1a; ​ 输入: 1->2->3->4->5->NULL ​ 输出: 5->4-&…

如何设计高性能架构

高性能复杂度模型 高性能复杂度分析和设计 单机 集群 任务分配 将任务分配给多个服务器执行 复杂度分析 增加“任务分配器”节点&#xff0c;可以是独立的服务器&#xff0c;也可以是SDK任务分配器需要管理所有的服务器&#xff0c;可以通过配置文件&#xff0c;也可以通过…

RK3588移植-opencv交叉编译aarch64

文章参考&#xff1a;https://blog.csdn.net/KayChanGEEK/article/details/80365320 文章目录概括准备资源交叉编译OPENCV修改CMakelist文件将lib库复制到/lib目录注意&#xff1a;本文中的所有配置相关路径都与当前安装的路径有关&#xff0c;需要根据自己的环境进行自行修改&…

『Java课设』JavaSwing+MySQL实现学生成绩管理系统

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位喜欢写作&#xff0c;计科专业大三菜鸟 &#x1f3e1;个人主页&#xff1a;starry陆离 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 『Java课设』JavaSwingMySQL实现学生成绩管理系统前言1.开…

SparkMlib 之随机森林及其案例

文章目录什么是随机森林&#xff1f;随机森林的优缺点随机森林示例——鸢尾花分类什么是随机森林&#xff1f; 随机森林算法是机器学习、计算机视觉等领域内应用极为广泛的一个算法&#xff0c;它不仅可以用来做分类&#xff0c;也可用来做回归即预测&#xff0c;随机森林机由…

RabbitMQ之可靠性分析

在使用任何消息中间件的过程中&#xff0c;难免会出现消息丢失等异常情况&#xff0c;这个时候就需要有一个良好的机制来跟踪记录消息的过程&#xff08;轨迹溯源&#xff09;&#xff0c;帮助我们排查问题。在RabbitMQ 中可以使用Firehose 功能来实现消息追踪&#xff0c;Fire…

艾美捷MTT细胞增殖检测试剂盒结果示例引用文献

艾美捷MTT细胞增殖检测试剂盒测定原理&#xff1a; 该试剂盒提供了比色形式测量和监测细胞增殖&#xff0c;含有足够的试剂用于评估在96孔板中进行960次测定或在24孔板中进行192次测定。细胞可以被镀&#xff0c;然后用影响增殖的化合物或药剂。然后用增殖试剂检测细胞&#x…

3.矩阵计算及导数基础

1. 梯度 将导数拓展到向量。 1. 标量对向量求导 x是列向量&#xff0c;y是标量&#xff0c;求导之后变成了行向量 ps&#xff1a; x1^2 2x2^2 这个函数可以画成等高线,对于&#xff08;x1&#xff0c;x2&#xff09;这个点&#xff0c;可以做等高线的切线&#xff0c;再做出…

Spark Streaming(二)

声明&#xff1a; 文章中代码及相关语句为自己根据相应理解编写&#xff0c;文章中出现的相关图片为自己实践中的截图和相关技术对应的图片&#xff0c;若有相关异议&#xff0c;请联系删除。感谢。转载请注明出处&#xff0c;感谢。 By luoyepiaoxue2014 B站&#xff…

动态规划算法(2)最长回文子串详解

文章目录最长回文字串动态规划代码示例前篇&#xff1a; &#xff08;1&#xff09;初识动态规划 最长回文字串 传送门&#xff1a; https://leetcode.cn/problems/longest-palindromic-substring/description/ 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 s &qu…

大数据学习:使用Java API操作HDFS

文章目录一、创建Maven项目二、添加依赖三、创建日志属性文件四、在HDFS上创建文件五、写入HDFS文件1、将数据直接写入HDFS文件2、将本地文件写入HDFS文件六、读取HDFS文件1、读取HDFS文件直接在控制台显示2、读取HDFS文件&#xff0c;保存为本地文件一、创建Maven项目 二、添加…

Spring Security 中重要对象汇总

前言 已经写了好几篇关于 Spring Security 的文章了&#xff0c;相信很多读者还是对 Spring Security 的云里雾里的。这是因为对 Spring Security 中的对象还不了解。本文就来介绍介绍一下常用对象。 认证流程 SecurityContextHolder 用户认证通过后&#xff0c;为了避免用…