AntD-tree组件使用详析

news2024/11/13 12:56:04

目录

一、selectedKeys与onSelect

官方文档

代码演示

onSelect 

注意事项 

二、expandedKeys与onExpand

官方文档

代码演示

onExpand 

注意事项 

三、loadedKeys与onLoad和onExpand

官方文档

代码演示

 onExpand与onLoad:​

注意事项 

四、loadData

官方文档

代码演示

 loadData: 

注意事项 

五、树节点局部节点刷新

实现思路 

代码演示

六、递归获取与修改数据

获取数据

修改数据

七、总结


        最近一周都在忙关于文件管理的东西,从提出这个需求到目前实现为止已经快一周的时间了。从最开始的找插件,然后发现没有插件可以用,再到打算自己手撸一个发现手写树状图过于困难,且因为技术力的原因估计会留下很多坑。所以在经过多方考虑以后觉得还是通过 antd-tree+手动控制的方式去实现一个文件管理页面。

        下面我将着重讲解我在使用antd-tree组件时遇到的各种苦难已经官方文档中方法属性的应用。

一、selectedKeys与onSelect

官方文档

参数说明类型版本
selectedKeys(受控)设置选中的树节点string[]
onSelect点击树节点触发function(selectedKeys, e:{selected: bool, selectedNodes, node, event})

代码演示

onSelect 

形参:

selectedKeys: 代表当前选中的树节点的key值。获取的值的格式为:[ 'key' ]。可以通过selectedKeys[0]取值。

info: 当前选择的树节点的信息。可以通过info.selectedNodes.props.dataRef.children来获取当前节点的子节点。

注意事项 

        这里需要注意的是selectedKeys是一个数组类型。有且只有一个当前选中的节点key。一旦点击其他节点,数组内的值就会被替换。

如果树组件设置了selectedKeys这个属性,那么需要在onSelect函数执行时将值赋给该属性。

二、expandedKeys与onExpand

官方文档

参数说明类型默认值版本
expandedKeys(受控)展开指定的树节点string[][]
onExpand展开/收起节点时触发function(expandedKeys, {expanded: bool, node})-

代码演示

onExpand 

 形参:

expandedKeys: 代表当前打开的树节点的key值。

info: 当前打开的树节点的信息。

注意事项 

        这里需要注意的是,expandedKeys也是一个数组的格式,但它与selectedKeys的区别是selectedKeys始终是一个长度为0或1的数组,而expandedKeys则是包含所有被打开的树节点的key值。

三、loadedKeys与onLoad和onExpand

官方文档

参数说明类型默认值版本
loadedKeys(受控)已经加载的节点,需要配合 loadData 使用string[][]3.7.0
onExpand展开/收起节点时触发function(expandedKeys, {expanded: bool, node})-
onLoad节点加载完毕时触发function(loadedKeys, {event, node})-3.7.0

代码演示

 onExpand与onLoad:

形参:

loadedKeys:已经完成加载的树节点的key,是一个数组的数据类型。

注意事项 

       这里需要注意的是loadedKeys是一个数组数据类型,且可以存放多个key。一旦被加载过以后,无论怎么点击都不会再触发重新刷新重新加载了。如果想让其刷新,请移步至节点刷新。

四、loadData

官方文档

参数说明类型默认值版本
loadData异步加载数据function(node)-
loadedKeys(受控)已经加载的节点,需要配合 loadData 使用string[][]3.7.0
treeDatatreeNodes 数据,如果设置则不需要手动构造 TreeNode 节点(key 在整个树范围内唯一)array\<{key, title, children, [disabled, selectable]}>-

代码演示

 loadData: 

形参:

treeNode :要加载的树节点的信息。

注意事项 

        这里需要注意的是如果你的树节点,是通过点击以后再加载子节点,那么对于后端的数据格式返回可能就有一些要求了。比如 title 与 isLeaf 等。当然也可以在loadData中自行设置。

        loadData中代码的大概流程就是先判断 treeNode 是否有 children这个属性,注意是是否有这个属性,如果有这个属性但这个属性为空数组,在执行中也会判定为true从而不会执行更新操作,而是直接return出去。

五、树节点局部节点刷新

实现思路 

        因为tree的机制问题,当key节点加载过以后该节点将不会再被重新加载,因此如果我上传了一个文件,实际上服务器上已经有文件了,但因为节点刷新问题,该节点没有重新刷新,我就看不到对应的节点文件。因此需要进行局部节点刷新。

        满足节点刷新的条件有这几个。

  • 1. loadedKeys中移除该节点的key值和其子孙节点的key值
  • 2. treeData中将该节点的children属性删除
  • 3. expandedKeys中移除A节点下的所有子孙节点的key值

        完成这三点以后再将selectedKeys选取到该节点 ,并将以上数据重新赋值给对应的属性即可完成节点刷新操作。

代码演示

 updateTree = () =>{
        const { selectedKeys , expandedKeys, loadedKeys, treeData } = this.state
        // 获取新的expandedKeys数组,不包含该节点及子节点
        const newExpandedKeys = expandedKeys.filter(item =>{
            return item.indexOf(selectedKeys[0]) == -1
        })
        // 获取新的loadedKeys数组,不包含该节点及子节点
        const newLoadedKeys = loadedKeys.filter(item =>{
            return item.indexOf(selectedKeys[0]) == -1
        })
        const newTreedata = treeData
        this.setState({
            expandedKeys: [...newExpandedKeys,...[`${selectedKeys[0]}`]],
            loadedKeys: [...newLoadedKeys],
            treeData: this.removeShowData(newTreedata),
            selectedKeys: [`${selectedKeys[0]}`],
        })
    }
    // 获取新的treeData数据
    removeShowData = (datas) => {
        const { selectedKeys } = this.state
        const newData = datas;
        function setGrayNode(data){ //遍历树  获取id数组
            for(var i=0;i<data.length;i++){
              if(data[i].key == selectedKeys[0]){// 如果某一个节点是禁用的,它的所有子节点都应该禁用
                delete data[i].children
                continue;
              } else {
                if(data[i].children){// 如果当前节点有子节点,就递归调用一次
                  setGrayNode(data[i].children);
                }
              }
            }
          }
          setGrayNode(newData)
          return newData;
    }

        这里需要注意的是 expandedKeys 虽然删除了当前节点,但要想操作通顺需要再次手动赋值,将该节点打开,并获取新的数据。这样就省去了用户需要再次点击节点的尴尬情况。

六、递归获取与修改数据

        因为这是一个树状图,数据结构也稍微复杂一些,所以获取数据时难免需要通过递归拿取数据。所以需要一个递归函数取实现数据的拿取。

获取数据

    //递归获取Showdata数据 
    getShowData = (datas) => {
        const { selectedKeys } = this.state
        datas.map(item => {
            const { key, children } = item
            if (key == selectedKeys[0]) {
                //符合条件
                this.setState({
                    showData: datas
                })
                return
            }
             //如果有孩子,再次调用自己,将孩子传进去。
            if (children && children.length > 0) {
                this.getShowData(children)
            }
        })
    }

修改数据

    // 获取新的treeData数据
    removeShowData = (datas) => {
        const { selectedKeys } = this.state
        const newData = datas;
        function setGrayNode(data){ //遍历树  获取id数组
            for(var i=0;i<data.length;i++){
              if(data[i].key == selectedKeys[0]){// 如果某一个节点是禁用的,它的所有子节点都应该禁用
                delete data[i].children
                continue;
              } else {
                if(data[i].children){// 如果当前节点有子节点,就递归调用一次
                  setGrayNode(data[i].children);
                }
              }
            }
          }
          setGrayNode(newData)
          return newData;
    }

七、总结

        一个星期下来还是比较累的,原因是因为组件使用不熟练,且自己的技术力较弱导致的,但好在也顺利完成任务,倒也没有什么大碍。记录一下这一个星期以来遇到的一些问题和实践吧。前端小白一枚,如有错误欢迎指正。

        源码:

import React, { Component } from 'react';
import { connect } from 'dva';
import {
    Modal,
    Button,
    Tree,
    Row,
    Col,
    Empty,
    Tooltip,
    Icon,
    Upload,
    Popconfirm,
    Select,
    Spin,
    notification
} from 'antd';
import { formatMessage, FormattedMessage } from 'umi-plugin-locale';
import globalUtil from '../../utils/global'
import download from '@/utils/download';
import apiconfig from '../../../config/api.config';
import SVG from './svg';
import styles from './index.less';

const { TreeNode, DirectoryTree } = Tree;
@connect(
    ({ appControl }) => ({
        appDetail: appControl.appDetail,
    })
)

class Index extends Component {
    constructor(props) {
        super(props);
        this.state = {
            treeData: [],
            selectedKeys: [],
            expandedKeys: [],
            pathArr: [],
            keyArr: [],
            dowloadArr: [],
            path: '',
            podsList: [],
            selectDefaultValue: '',
            hostPath: this.props && this.props.hostPath,
            selectLoading: false,
            treeDataLoading: false,
            loadedKeys:[]
        }
    }
    componentDidMount() {
        this.fetchInstanceInfo()
    }
    // 获取podname
    fetchInstanceInfo = () => {
        const { dispatch } = this.props;
        dispatch({
            type: 'appControl/fetchPods',
            payload: {
                team_name: globalUtil.getCurrTeamName(),
                app_alias: this.props.appAlias,
            },
            callback: res => {
                if (res && res.list) {
                    this.setState({
                        podsList: res.list.new_pods,
                        selectDefaultValue: res && res.list && res.list.new_pods[0] && res.list.new_pods[0].pod_name,
                        selectLoading: true
                    }, () => {
                        if (this.props.isType) {
                            this.determineStorageType()
                        }else{
                            this.getListFiles()
                        }
                    })
                }
            }
        });
    };
    // 获取文件类型
    determineStorageType = () => {
        this.props.dispatch({
            type: 'appControl/determineStorageType',
            payload: {
                team_name: globalUtil.getCurrTeamName(),
                group_id: this.props.appAlias,
                region_name: globalUtil.getCurrRegionName(),
                pod_name: this.state.selectDefaultValue,
                namespace: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.namespace,
                volume_path: this.props && his.props.volumePath,
            },
            callback: res => {
                if(res){
                    this.setState({
                        hostPath: res.bean,
                    },()=>{
                        this.getListFiles()
                    })
                }
            }
        });
    };
    // 获取文件列表
    getListFiles = () => {
        this.props.dispatch({
            type: 'appControl/getListFiles',
            payload: {
                team_name: globalUtil.getCurrTeamName(),
                group_id: this.props.appAlias,
                region_name: globalUtil.getCurrRegionName(),
                pod_name: this.state.selectDefaultValue,
                host_path: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}` : this.state.hostPath,
                extend_method: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method
            },
            callback: res => {
                if (res && res.list) {
                    res.list.map((item, index) => {
                        item.key = index,
                            item.isLeaf = item.is_leaf
                    })
                    this.setState({
                        treeData: res.list,
                        showData: res.list,
                        treeDataLoading: true
                    })
                }
            },
            handleError: res =>{
                if(res){
                    notification.error({ message: formatMessage({id:'componentOverview.body.DirectoryPersistence.error'}) });
                    this.setState({
                        showData: [],
                        treeData: []
                    })
                }
            }
        });
    }
    // 获取文件列表
    updataListFiles = (path) => {
        this.setState({
            treeDataLoading: false
        },()=>{
            this.props.dispatch({
                type: 'appControl/getListFiles',
                payload: {
                    team_name: globalUtil.getCurrTeamName(),
                    group_id: this.props.appAlias,
                    region_name: globalUtil.getCurrRegionName(),
                    pod_name: this.state.selectDefaultValue,
                    host_path: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}${path}` : `${this.state.hostPath}${path}`,
                    extend_method: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method
                },
                callback: res => {
                    if (res && res.list) {
                        res.list.map((item, index) => {
                            item.key = index,
                            item.isLeaf = item.is_leaf
                        })
                        this.setState({
                            treeData: res.list,
                            showData: res.list,
                            treeDataLoading: true
                        })
                    }
                },
                handleError: res =>{
                    if(res){
                        notification.error({ message: formatMessage({id:'componentOverview.body.DirectoryPersistence.error'}) });
                        this.setState({
                            showData: [],
                            treeData: []
                        })
                    }
                }
            });
        })
    }
    // 加载树图
    onLoadData = treeNode =>
        new Promise(resolve => {
            if (treeNode.props.children) {
                resolve();
                return;
            }
            setTimeout(() => {
                this.props.dispatch({
                    type: 'appControl/getListFiles',
                    payload: {
                        team_name: globalUtil.getCurrTeamName(),
                        group_id: this.props.appAlias,
                        region_name: globalUtil.getCurrRegionName(),
                        pod_name: this.state.selectDefaultValue,
                        host_path: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}/${this.state.path}` : `${this.state.hostPath}/${this.state.path}`,
                        extend_method: this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method
                    },
                    callback: res => {
                        if (res) {
                            if (res.list && res.list.length == 0) {
                                this.setState({
                                    treeData: [...this.state.treeData],
                                    showData: res.list
                                });
                                treeNode.props.dataRef.children = []
                                resolve();
                            } else {
                                const arr = res.list
                                arr.map((item, index) => {
                                    item.key = `${treeNode.props.eventKey}-${index}`
                                    item.isLeaf = item.is_leaf
                                })
                                treeNode.props.dataRef.children = arr
                                this.setState({
                                    treeData: [...this.state.treeData],
                                    showData: res.list
                                });
                                resolve();
                            }
                        }
                    }
                });
            }, 100)
        });
    // 渲染函数
    renderTreeNodes = data =>
        data && data.map((item, index) => {
            if (item.isLeaf) {
                return (
                    <TreeNode title={item.title} key={item.key} dataRef={item} >
                        {this.renderTreeNodes(item.children)}
                    </TreeNode>
                );
            }
            return null;
        });
    //选择树节点 
    onSelect = (selectedKeys, info) => {
        // 选择为空时直接return
        if (selectedKeys && selectedKeys.length == 0) {
            return null
        }
        if (info) {
            const { selectedNodes } = info
            const { props } = selectedNodes[0]
            const { dataRef } = props
            this.setState({
                selectedKeys: selectedKeys,
                expandedKeys: this.state.expandedKeys.includes(selectedKeys[0]) ? [...this.state.expandedKeys] : [...this.state.expandedKeys, ...selectedKeys],
                showData: dataRef.children || this.state.showData,
                dowloadArr: [],
                pathArr: [],
                path: ''
            }, () => {
                this.getPath()
            })
        } else {
            this.setState({
                selectedKeys: selectedKeys,
                expandedKeys: this.state.expandedKeys.includes(selectedKeys[0]) ? [...this.state.expandedKeys] : [...this.state.expandedKeys, ...selectedKeys],
                dowloadArr: [],
                pathArr: [],
                path: ''
            }, () => {
                this.getPath()
            })
        }
    }
    onLoad = (loadedKeys) =>{
        this.setState({
            loadedKeys: loadedKeys
        })
      }
    // 展开树图
    onExpand = (expandedKeys, info) => {
        let newLoadKeys = this.state.loadedKeys
        if (this.state.expandedKeys.length > expandedKeys.length) {
            //  当是收起的时候,把这个收起的节点从loadedKeys中移除
          newLoadKeys = this.state.loadedKeys.filter((i) => expandedKeys.includes(i))
        }
        this.setState({
            expandedKeys: expandedKeys,
            selectedKeys: [`${info.node.props.dataRef.key}`],
            showData: info.node.props.dataRef.children,
            loadedKeys: newLoadKeys
        }, () => {
            this.getPath()
        })
    };
    // 获取后缀名
    getSvgIcon = (name) => {
        if (name) {
            const str = name.substr(name.lastIndexOf('.') + 1)
            return `${str}`
        }
    }
    // 鼠标点击
    folderClick = (data) => {
        // 判断data数据是否有孩子,如果没有就加载,如果有就
        if (data && data.children && data.children.length > 0) {
            this.setState({
                expandedKeys: [...this.state.expandedKeys, ...[`${data.key}`]],
                selectedKeys: [`${data.key}`],
                showData: data.children,
                dowloadArr: []
            }, () => {
                this.getPath()
            })
        } else {
            this.setState({
                expandedKeys: [...this.state.expandedKeys, ...[`${data.key}`]],
                selectedKeys: [`${data.key}`],
                dowloadArr: []
            }, () => {
                this.getPath()
            })
        }
    }
    //递归获取Showdata数据 
    getShowData = (datas) => {
        const { selectedKeys } = this.state
        datas.map(item => {
            const { key, children } = item
            if (key == selectedKeys[0]) {
                this.setState({
                    showData: datas
                })
            }
            if (children && children.length > 0) {
                this.getShowData(children)
            }
        })
    }
    // 获取key值的path数据
    getPathData = (data) => {
        const { treeData, keyArr } = this.state
        data.map(item => {
            const { title, children } = item
            if (keyArr.indexOf(`${item.key}`) != -1) {
                const arr = this.state.pathArr
                arr.push(title)
                this.setState({
                    pathArr: arr
                })
            }
            if (children && children.length > 0) {
                this.getPathData(children)
            }
        })
    }
    //递归获取path数据 
    getPath = () => {
        const { selectedKeys, treeData, pathArr } = this.state
        if (selectedKeys == []) {
            return
        }
        if (selectedKeys && selectedKeys[0]) {
            const length = selectedKeys[0].length
            const str = selectedKeys[0]
            const arr = str.split("-")
            const keyArr = []
            for (let index = 0; index < arr.length + 1; index++) {
                const newarr = arr.slice(0, index)
                const newstr = newarr.join("-")
                keyArr.push(newstr)
            }
            keyArr.shift();
            this.setState({
                keyArr: keyArr,
                pathArr: []
            }, () => {
                this.getPathData(treeData)
            })
            setTimeout(() => {
                const path = this.state.pathArr.join("/")
                this.setState({
                    path: path
                })
            }, 100)
        }
    }
    // 返回上一级
    goBack = () => {
        const { selectedKeys } = this.state
        // 如果选择为空,则展示所有数据
        if (selectedKeys[0] == undefined) {
            return
        }
        // 如果选择有值且值不大于1
        if ((selectedKeys[0]).indexOf("-") == -1) {
            this.setState({
                selectedKeys: [],
                showData: this.state.treeData,
                dowloadArr: []
            }, () => {
                this.getPath()
            })
            // 如果选择有值且值大于1
        } else {
            this.getShowData(this.state.treeData)
            this.setState({
                selectedKeys: [`${selectedKeys[0].substring(0, (selectedKeys[0]).lastIndexOf("-"))}`],
                dowloadArr: []
            }, () => {
                this.getPath()
            })
        }
    }
    // 下载
    dowloadTitle = (val) => {
        const { dowloadArr } = this.state
        setTimeout(() => {
            if (dowloadArr.includes(val)) {
                const arr = []
                dowloadArr.map(item => {
                    if (item != val) {
                        arr.push(item)
                    }
                })
                this.setState({
                    dowloadArr: [...arr]
                })
            } else {
                const arr = []
                arr.push(val)
                this.setState({
                    dowloadArr: [...this.state.dowloadArr, ...arr]
                })
            }
        }, 10)
    }
    // 下拉框选择
    selectChange = (val) => {
        this.setState({
            selectDefaultValue: val
        },()=>{
            this.getListFiles()
        })
    }
    fileDownload = () => {
        const { dowloadArr } = this.state
        if(dowloadArr.length == 0 ){
            notification.info({ message: formatMessage({id:'componentOverview.body.DirectoryPersistence.download'}) });
        }else{
            dowloadArr.map(item =>{
                this.fileDownloadApi(item)
            })
        }
        setTimeout(()=>{
            this.setState({
                dowloadArr:[]
            })
        },100)
    }
    // 下载接口
    fileDownloadApi = ( title ) =>{
        const dowloadPath = this.state.path ? this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}/${this.state.path}` : `${this.state.hostPath}/${this.state.path}` : this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}` : `${this.state.hostPath}`;
        const host = apiconfig.baseUrl;
        const url = host.slice(0,host.lastIndexOf(":"))
        // const path = `${url}:6060/v2/ws/download/${title}?path=${dowloadPath}`
        const path = `http://47.104.161.96:6060/v2/ws/download/${title}?path=${dowloadPath}`
        this.download(`${path}`,title)
    }
    download = (downloadPath, title) => {
        console.log(title.indexOf("txt") == -1,"title.indexOf() == -1");
        if(title.indexOf("txt") == -1){
            let aEle = document.querySelector('#down-a-element');
            if (!aEle) {
              aEle = document.createElement('a');
              aEle.setAttribute('target', '_blank')
              aEle.setAttribute('download', title);
              document.body.appendChild(aEle);
            }
            aEle.href = downloadPath;
            if (document.all) {
              aEle.click();
            } else {
              const e = document.createEvent('MouseEvents');
              e.initEvent('click', true, true);
              aEle.dispatchEvent(e);
            }
        }else{
            var element = document.createElement('a');
            element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(title));
            element.setAttribute('download', title);
            element.style.display = 'none';
            document.body.appendChild(element);
            element.click();
            document.body.removeChild(element);
        }
      };
    uploadChange = info => {
        const { path, selectedKeys } = this.state
        if (info && info.file && info.file.status === 'done') {
            notification.success({ message: formatMessage({id:'notification.success.upload'})});
            if(selectedKeys[0] == undefined){
                this.getListFiles()
            }else{
                this.updateTree()
            }
        } else if (info && info.file && info.file.status === 'error') {
            notification.error({ message: formatMessage({id:'notification.error.update'}) });
        }
      };
    updateTree = () =>{
        const { selectedKeys , expandedKeys, loadedKeys, treeData } = this.state
        // 获取新的expandedKeys数组,不包含该节点及子节点
        const newExpandedKeys = expandedKeys.filter(item =>{
            return item.indexOf(selectedKeys[0]) == -1
        })
        // 获取新的loadedKeys数组,不包含该节点及子节点
        const newLoadedKeys = loadedKeys.filter(item =>{
            return item.indexOf(selectedKeys[0]) == -1
        })
        const newTreedata = treeData
        this.setState({
            expandedKeys: [...newExpandedKeys,...[`${selectedKeys[0]}`]],
            loadedKeys: [...newLoadedKeys],
            treeData: this.removeShowData(newTreedata),
            selectedKeys: [`${selectedKeys[0]}`],
        })
    }
    // 获取新的treeData数据
    removeShowData = (datas) => {
        const { selectedKeys } = this.state
        const newData = datas;
        function setGrayNode(data){ //遍历树  获取id数组
            for(var i=0;i<data.length;i++){
              if(data[i].key == selectedKeys[0]){// 如果某一个节点是禁用的,它的所有子节点都应该禁用
                delete data[i].children
                continue;
              } else {
                if(data[i].children){// 如果当前节点有子节点,就递归调用一次
                  setGrayNode(data[i].children);
                }
              }
            }
          }
          setGrayNode(newData)
          return newData;
    }
    render() {
        const {
            selectedKeys,
            expandedKeys,
            showData,
            path,
            dowloadArr,
            podsList,
            selectDefaultValue,
            selectLoading,
            treeDataLoading,
            hostPath,
            loadedKeys
        } = this.state
        const upLoadPath = this.state.path ? this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}/${this.state.path}` : `${this.state.hostPath}/${this.state.path}` : this.props.appDetail && this.props.appDetail.service && this.props.appDetail.service.extend_method == 'state_multiple' ? `${this.state.hostPath}/${this.state.selectDefaultValue}` : `${this.state.hostPath}`;
        const host = apiconfig.baseUrl;
        const url = host.slice(0,host.lastIndexOf(":"))
        // const upload = `${url}:6060/v2/ws/upload`
        const upload = `http://47.104.161.96:6060/v2/ws/upload`
        const props = {
            action: upload,
            data:{path: upLoadPath},
            method:"post",
            name:'packageTarFile',
        };
        const isFile = showData.filter(item => { return item.title.indexOf('.') == -1 })
        const notFile = showData.filter(item => { return item.title.indexOf('.') != -1 })
        const folder = []
        isFile.map((item,index) =>{
          if(item.isLeaf == true){
            folder.unshift(item)
          }else{
            folder.push(item)
          }
        })
        const showDataArr = [...folder,...notFile]
        return (
            <div>
                <Modal
                    className={styles.ModalStyle}
                    title={<>
                        {formatMessage({id:'componentOverview.body.DirectoryPersistence.example'})}
                        <Select
                            value={selectDefaultValue}
                            style={{ maxWidth: 184, marginLeft: 5 }}
                            onChange={this.selectChange}
                            loading={!selectLoading}
                        >
                            {podsList && podsList.length > 0 &&
                                podsList.map(item => {
                                    return <Select.Option value={item.pod_name}>{item.pod_name}</Select.Option>
                                })
                            }
                        </Select>
                    </>}
                    visible={true}
                    width={1000}
                    closable={false}
                    footer={
                        <>
                            <Upload
                                {...props}
                                showUploadList={false}
                                multiple
                                onChange={this.uploadChange}
                                // directory={true}
                            >
                                <Button type="primary" style={{ marginRight: 10 }}>
                                    <Icon type="upload" /> {formatMessage({id:'applicationMarket.Offline.upload'})}
                                </Button>
                            </Upload>
                            <Button type="primary" onClick={this.fileDownload}>
                                <Icon type="download" />
                                {formatMessage({id:'button.download'})}
                            </Button>
                            <Button onClick={this.props.isShow}>
                                {formatMessage({id:'popover.cancel'})}
                            </Button>
                        </>
                    }
                >
                    {treeDataLoading ? (
                        <Row>
                            <Col span={6}>
                                <Tree
                                    loadData={this.onLoadData}
                                    onSelect={this.onSelect}
                                    selectedKeys={selectedKeys}
                                    onExpand={this.onExpand}
                                    expandedKeys={expandedKeys}
                                    switcherIcon={<Icon type="down" />}
                                    onLoad={this.onLoad}   
                                    loadedKeys={loadedKeys} 
                                >
                                    {this.renderTreeNodes(this.state.treeData)}
                                </Tree>
                            </Col>
                            <Col span={18} style={{ position: 'relative' }}>
                                <div className={styles.goBack}>
                                    <button onClick={this.goBack}>{SVG.getSvg("goBack", 12)}{formatMessage({id:'componentOverview.body.DirectoryPersistence.return'})}</button>
                                </div>
                                <div className={styles.iconShow}>
                                    {showDataArr && showDataArr.length > 0 ? (
                                        showDataArr.map((item, index) => {
                                            const { title, isLeaf } = item
                                            if (isLeaf) {
                                                return <div className={styles.outerLayer} style={{ cursor: "pointer" }} onDoubleClick={() => this.folderClick(item)}>
                                                    <div>
                                                        {SVG.getSvg('file', 70)}
                                                    </div>
                                                    <div>
                                                        <Tooltip placement="top" title={item.title}>
                                                            {item.title}
                                                        </Tooltip>
                                                    </div>
                                                </div>
                                            } else {
                                                return <div className={styles.outerLayer} onClick={() => this.dowloadTitle(item.title)} style={{ background: dowloadArr.includes(item.title) ? "#e6f7ff" : '#fff' }}>
                                                    <div>
                                                        {SVG.getSvg(this.getSvgIcon(title), 70)}
                                                    </div>
                                                    <div>
                                                        <Tooltip placement="top" title={item.title}>
                                                            {item.title}
                                                        </Tooltip>
                                                    </div>
                                                </div>
                                            }
                                        })
                                    ) : (
                                        <Empty className={styles.emptyStyle} />
                                    )}
                                </div>

                            </Col>
                        </Row>
                    ) : (
                        <Spin size="large" style={{
                            width: '100%',
                            height: 400,
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                        }} />
                    )}

                </Modal>
            </div>
        );
    }
}

export default Index;

        

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

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

相关文章

从“服务”,到“赋能”,日日顺再次定义供应链生态建设

在众多不确定因素的交织下&#xff0c;当下的供应链企业变革呈现出前所未有的紧迫感。一体化、全链路的趋势&#xff0c;为企业的发展指明方向&#xff0c;与此同时数字化与科技化开始承托供应链管理能力的升级与变革。 2月15日&#xff0c;由日日顺供应链、运联智库联合举办的…

CVE-2021-42278 CVE-2021-42287域内提权漏洞

漏洞介绍2021 年 11 月 9 日&#xff0c;国外研究员在推特上发布了AD相关的 CVE&#xff0c;CVE-2021-42278 & CVE-2021-42287 &#xff0c;两个漏洞组合可导致域内普通用户权限提升至域管权限。CVE-2021-42278&#xff1a;是一个安全绕过漏洞&#xff0c;允许通过修改机器…

4.4 MQC

1. 实验目的 熟悉MQC的应用场景掌握MQC的配置方法2. 实验拓扑 实验拓扑如图4-10所示: 图4-10:MQC 3. 实验步骤 (1) IP地址的配置 AR1的配置 <Huawei>system-view

【单目标优化算法】蜣螂优化算法(Dung beetle optimizer,DBO)(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…

合宙Air780E|iot|update|FOTA|LuatOS-Air开发|LuatOS-SOC接口|官方demo|学习(17):FOTA(远程升级)

一. 概述 update是物联网中比较常用的功能&#xff0c;本文介绍如何用Air780E开发板&#xff0c;如何做update升级。 LuatOS-Air开发模式下&#xff0c;固件分为两部分&#xff1a;core和script 远程升级时&#xff1a;core为差分升级&#xff1b;script为全量覆盖升级 远程…

Spring高级(原理)

一、Spring创建Bean personService -> 构造方法 -> 普通对象 -> 依赖注入&#xff08;byType->byName&#xff09; -> 初始化前(PostConstruct) -> 初始化(InitializingBean) -> 初始化后(AOP) -> 代理对象 -> 将代理对象放入到Map单例池中 -> B…

WGCNA | 值得你深入学习的生信分析方法!~(网状分析-第五步-高级可视化)

1写在前面 前面我们用WGCNA分析完成了一系列的分析&#xff0c;聚类分割模块。&#x1f970; 随后进一步筛选&#xff0c;找到与我们感兴趣的表型或者临床特征相关的模块&#xff0c;而且进行了模块内部分析。&#x1f618; 再然后是对感兴趣模块进行功能注释&#xff0c;了解模…

Mars3D Studio 的使用方法

Mars3D Studio的使用 1、介绍&#xff1a; mars3d Studio是mars3d研发团队于近期研发上线的一款 场景可视化编辑平台。拥有资源存档、团队协作、定制材质等丰富的功能。可以实现零代码构建一个可视化三维场景。 2、功能介绍 &#xff08;1&#xff09;数据上传&#xff1a…

代码随想录【Day16】| 110. 平衡二叉树、257. 二叉树的所有路径、404. 左叶子之和

110. 平衡二叉树 题目链接 题目描述&#xff1a; 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a;一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1: 给定二叉树 [3,9,20,null,nul…

物理层基本介绍

corset 0 告诉下行初始带宽是多少 initail DL BWP, 4g 是20M带宽&#xff0c;5G是FR1 如果5G是全带宽的话&#xff0c;手机很快就会没电了。 告诉手机带宽会分布在某一个带宽里面去&#xff0c;将手机的带宽调整就行。 DCI&#xff0c;告诉手机&#xff0c;未来的某一个时刻&a…

【MyBatis】第九篇:mybatis逆向工程插件----mybatis-generator

本篇聊mybatis逆向工程&#xff0c;但是这个和安卓逆向不一样&#xff0c;不是说反编译&#xff0c;破解什么加密 &#xff0c;最后打包。而是通过一某插件&#xff0c;快速生成一个mybatis项目的结构而已。 简单的说就是&#xff0c;通过先创建的数据表&#xff0c;由框架通过…

【1139. 最大的以 1 为边界的正方形】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个由若干 0 和 1 组成的二维网格 grid&#xff0c;请你找出边界全部由 1 组成的最大 正方形 子网格&#xff0c;并返回该子网格中的元素数量。如果不存在&#xff0c;则返回 0。 示例 1&#…

浮点数值计算精度丢失问题剖析及解决方法

文章目录1、原因分析2、解决方法2.1、Java中使用 BigDecimal 类2.2、JavaScript 中解决计算精度丢失的问题3、使用建议1、原因分析 首先我们来看个反直觉的浮点数值计算 System.out.println(0.3*3);有的同学可能要问为啥不是0.9&#xff1f; 首先要知道为什么会产生这个问题…

Mybatis的Mapper接口代理机制

提示&#xff1a;本文章基于B站动力节点的课程仿写 文章目录前言一、解析mybatis-config.xml1.1 引入dom4j依赖1.2 解析mybatis-config.xml1.3 解析mapper映射文件二、引入javassist2.1 引入javassist依赖2.基于mybatis的javassist来实现该功能前言 本文章基于B站动力节点的课…

算法训练营DAY54|583. 两个字符串的删除操作、72. 编辑距离

583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/delete-operation-for-two-strings/这道题也是对于编辑距离的铺垫题目&#xff0c;是可以操作两个字符串的删除&#xff0c;使得两个字符串的字符完全相同&#xff0c;这道题可…

利用vite插件开发,实现工程化打包,建议收藏

为什么需要工程化打包&#xff1f; vue3vite的工程&#xff0c;普遍都会在项目public文件夹&#xff0c;创建一个config.js文件&#xff0c;存放一些配置态的数据&#xff0c;用于在产品上线后&#xff0c;可能会根据需要修改参数值&#xff0c;从而达到线上配置数据目的。 但…

第0章 一些你可能正感到迷惑的问题

操作系统是什么 操作系统是控制管理计算机系统的硬软件&#xff0c;分配调度资源的系统软件。 由操作系统把资源获取到后台给用户进程&#xff0c;但为了保护计算机系统不被损坏&#xff0c;不允许用户进程直接访问硬件资源。 操作系统相当于是一个分配资源的机构&#xff0c;…

【C++】string类(下)

文章目录1.迭代器(正向遍历)begin有两个版本2.反向迭代器(反向遍历)rbegin由两个版本3. at4. insert ——头插在pos位置前插入一个字符串在pos位置前插入n个字符在迭代器前插入一个字符5. erase从pos位置开始删除len个字符从迭代器位置开始删除6. replace——替换从pos位置开始…

【Linux】进程终止进程等待

文章目录进程创建fork函数初识fork函数返回值写时拷贝fork常规用法fork调用失败的原因进程终止进程退出场景进程常见退出方法进程等待进程等待必要性进程等待的方法wait方法waitpid方法获取子进程status从操作系统层面理解waitpid阻塞状态和非阻塞状态阻塞等待例子:多进程创建和…

设计模式 - 模板方法模式详解

介绍&定义 模板模式&#xff0c;全称是模板方法设计模式&#xff0c;英文是 Template Method Design Pattern。在 GoF 的《设计模式》一书中&#xff0c;它是这么定义的&#xff1a; Define the skeleton of an algorithm in an operation, deferring some steps to subcl…