您的当前位置:首页>全部文章>文章详情

树形/树状组织结构

发表于:2024-09-13 14:00:28浏览:357次TAG: #树状图

引言

基于vue2-org-tree组件结合html快速生成树状组织结构,只需复制以下代码加以微调即可,方便又快捷

效果图

模块

vue2-org-tree.zip
模块下载后放置:网站运行目录/assets/libs/

前端

<link href="/assets/libs/vue2-org-tree/vue2-org-tree@1.3.6.css" rel="stylesheet" />
<script src="/assets/libs/vue2-org-tree/vue@2.7.16.js"></script>
<script src="/assets/libs/vue2-org-tree/vue2-org-tree@1.3.6.js"></script>
<script src="/assets/libs/vue2-org-tree/axios@1.7.7.js"></script>
<!--【vue2文档】https://v2.cn.vuejs.org/v2/guide/installation.html-->
<!--【axios文档】http://www.axios-js.com/zh-cn/docs/-->
<style lang="scss">
    .tree-node {
        /*color: #FFFFFF;*/
        /*background-color: orange;*/
        padding: 0px!important;
    }
    #app {
        width: 100%;
        overflow:scroll;
    }
</style>
<div class="" id="app">

    <div class="org-tree">
        <vue2-org-tree
                :data="treeData"
                :props="treeProps"
                :label-class-name="treeLabelClassName"
                :horizontal="horizontal"
                :collapsable="collapsable"
                :render-content="renderContent"
                @on-node-mouseover="mouseoverTreeNode"
                @on-node-mouseout="mouseoutTreeNode"
                @on-node-click="onTreeNode"
                @on-expand="onTreeExpand"
        />
    </div>

</div>
<script>

    new Vue({
        name: 'OrgTree',
        el: '#app',
        data () {
            return {
                //horizontal:true=从左到右展示;false=从上到下展示
                horizontal:false,
                /**
                 * collapsable:true=显示展开或收缩;false=不显示展开或收缩
                 * 当collapsable=true时,数据中必须要有 expand 字段才会生效
                 * expand=true展开;expand=false收缩
                 */
                collapsable:true,
                treeData:{},
                treeProps:{
                    label:'label',
                    children:'children',
                    expand:'expand',
                },
                // style标签里不能加 scoped 不然自定义样式无效
                treeLabelClassName:"tree-node",
            }
        },
        created () {
            const that = this
            that.getTreeData(0).then((data)=>{
                that.treeData = data
            })
        },
        methods: {
            // 获取数据
            getTreeData(id){
                // 执行API请求,这里数据写死
                const that = this
                return new Promise((resolve) => {
                    axios({
                        url:'tree_data',
                        method:'get',
                        params:{
                            id:id
                        },
                        headers:{
                            'content-type':'application/json'
                        }
                    })
                    .then(response => {
                        resolve(response.data);
                    })
                    .catch(error => {
                        console.error(error);
                    });
                })
            },
            // 渲染方法,可以自己组装标签,类似vue的render方法
            renderContent(h, node) {
                let color_str = ""
                if (node.is_vip) {
                    color_str = "color:#ff5722;"
                }
                return h('div', {}, [
                    h('p', {style:color_str+'margin:0px;border-bottom:1px solid #dddddd;padding:5px 10px;'}, node.label),
                    h('p', {style:'margin:0px;padding:5px 10px;font-size:14px;color:#c2c2c2;'}, '邀请:'+node.children_count+'人'),
                ]);
            },
            // 点击节点
            onTreeNode(e, node) {
                if (node.children_count > 0 && node.children.length == 0) {
                    const that = this
                    that.getTreeData(node.id).then((data)=>{
                        node.children = data
                    })
                }
                // console.log(node)
            },
            // 鼠标移入
            mouseoverTreeNode(e, node) {
                // console.log(node)
            },
            // 鼠标移出
            mouseoutTreeNode(e, node) {
                // console.log(node)
            },
            // 点击 展开 或 收缩
            onTreeExpand(e, node) {
                // console.log('点击 展开 或 收缩')
                node.expand = node.expand == true ? false : true

            }
        }
    })
</script>

后端

控制器

public function tree()
{
    $this->layout = '';
    return $this->view->fetch();
}
public function tree_data()
{
    $id = $this->request->param('id',0);
    $us = new \app\common\service\User();
    $tree = $us->org($id,5);
    if ($id == 0) {
        $tree = [
            'id' => 'top',
            'value' => 'top',
            'label' => '平台',
            'expand'=>true,
            'children'=>$tree,
            'children_count'=>count($tree)
        ];
    }
    return json($tree);
}

逻辑

public function org($id,$level = 3)
{
    if ($level == 0) {
        return [];
    }
    $level--;
    $model = new UserModel();
    $list = $model->field('id,username as label,vip_id,vip_expire_time')->with('vip')->where('pid',$id)->select();
    foreach ($list as &$user){
        $user['expand'] = true;
        $user['is_vip'] = $user['vip_id'] > 0;
        $user['value'] = $user['id'];
        $user['children'] = $this->org($user['id'],$level);
        $user['children_count'] = $model->where('pid',$user['id'])->count();
    }
    return $list;
}