实现组织树和增删改查 国电南瑞前端考试题目

前言

这是一个非常基础的 组织树 前端项目,不需要搭建环境,只需要引入一个 vue 库即可,复制粘贴代码块到 TXT 文本另存为 html 双击打开就能用。

我是没想到这次考试内容居然是在 A4 纸上用水性笔手写出来一棵树并带有增删改查功能。1个半小时的考试时间,提示可以用任意框架,我就是个傻X非要钻牛角尖偏不使用成熟的框架、或者内置写好的组件,导致代码只写完了一部分,最后喜提50分,就差10分及格气死我了,所以考完试复盘写下了这个 Demo 顺便复习一下 CSS、JS。

功能

1.展示默认树内容;

2.鼠标悬浮选中树节点右键弹出菜单;

3.添加节点、删除节点、修改节点。

代码

先说个 BUG ,直接点 CSDN 复制代码会导致鼠标悬浮的 onmouseover Unicode 开头字符 &#111 变成 &#959 ,然后悬浮效果获取节点 ID 功能就失效了,点击复制后,务必手动替换一下 onmouseover,文章下方附有图片解释这个问题。
展示效果图放在最后面了,先上代码:

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>menu</title>
    <script src="./vue.min.js"></script>
</head>
<body>
<div id="app">
    <p>选择节点ID:{{hoverId}}&emsp;下一个ID:{{lastId}}</p>
    <div class="box" @click.right="fnRightClick($event)" @click.left="fnLeftClick($event)">
        <div class="tree" v-html="treeHtml"></div>
    </div>
    <div class="menu" v-if="menuVisibleState" :style="{left: menuLeft,top: menuTop}">
        <div class="btn" @click="fnOpenCreate()"><span>新增</span></div>
        <div class="btn" @click="fnOpenModify()"><span>修改</span></div>
        <div class="btn" @click="fnDelete()"><span>删除</span></div>
    </div>
    <div class="wrapper" v-if="formVisibleState">
        <div class="dialog">
            <div class="form">
                <div>
                    <label for="name">组织名称:</label>
                    <input type="text" id="name" v-model="name">
                </div>
                <div>
                    <label for="desc">组织描述:</label>
                    <textarea rows="10" id="desc" v-model="desc"></textarea>
                </div>
                <div class="btn-group">
                    <button @click="fnCommit()">提交</button>
                    <button @click="fnCloseCreate()">取消</button>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script>
    const app = new Vue({
        el: '#app',
        component: {},
        data: {
            id: '',
            name: '',
            desc: '',
            treeHtml: '',
            hoverId: '',
            lastId: 12,
            detail: {},
            menuLeft: 0,
            menuTop: 0,
            menuVisibleState: false,
            formVisibleState: false,
            orgDataList: [
                {
                    id: 1, label: '1', desc: '',
                    children: [
                        {
                            id: 4, label: '1-1', desc: '',
                            children: [
                                {id: 5, label: '1-1-1', desc: '', children: []}
                            ]
                        },
                        {
                            id: 10, label: '1-2', desc: '',
                            children: [
                                {id: 11, label: '1-2-1', desc: '', children: []}
                            ]
                        }
                    ]
                },
                {
                    id: 2, label: '2', desc: '',
                    children: [
                        {
                            id: 6, label: '2-1', desc: '',
                            children: [
                                {id: 7, label: '2-1-1', desc: '', children: []}
                            ]
                        }
                    ]
                },
                {
                    id: 3, label: '3', desc: '',
                    children: [
                        {
                            id: 8, label: '3-1', desc: '',
                            children: [
                                {id: 9, label: '3-1-1', desc: '', children: []}
                            ]
                        }
                    ]
                }
            ],
        },
        mounted() {
        },
        method: {}
    });

    // 打开创建窗口
    function fnOpenCreate() {
        app.menuVisibleState = false
        app.formVisibleState = true
    }

    // 打开修改窗口
    function fnOpenModify() {
        app.menuVisibleState = false
        app.formVisibleState = true
        fnOperateNode(app.hoverId, [], app.orgDataList, 'detail')
        app.id = app.detail.id
        app.name = app.detail.label
        app.desc = app.detail.desc
        app.children = app.detail.children
    }

    // 删除
    function fnDelete() {
        fnOperateNode(app.hoverId, [], app.orgDataList, 'delete')
        app.menuVisibleState = false
    }

    // 关闭创建窗口
    function fnCloseCreate() {
        app.formVisibleState = false
    }

    // 左键事件
    function fnLeftClick() {
        app.menuVisibleState = false
    }

    // 右键事件
    function fnRightClick(event) {
        event.preventDefault()
        let e = event
        app.menuLeft = e.clientX + "px"
        app.menuTop = e.clientY + "px"
        app.menuVisibleState = true
    }

    // 提交
    function fnCommit() {
        if (app.id) {
            let val = {
                id: app.id,
                label: app.name,
                desc: app.desc,
                children: app.children
            }
            fnOperateNode(app.id, val, app.orgDataList, 'modify')
            fnGeneratorTreeNode(app.orgDataList)
            app.id = ''
        } else {
            let val = {
                id: app.lastId,
                label: app.name,
                desc: app.desc,
                children: []
            }
            if (app.hoverId) {
                fnOperateNode(app.hoverId, val, app.orgDataList, 'create')
            } else {
                app.$set(app.orgDataList, app.orgDataList.length, val, 'create')
                fnGeneratorTreeNode(app.orgDataList)
            }
            app.lastId = app.lastId + 1
        }
        app.formVisibleState = false
        app.id = ''
        app.name = ''
        app.desc = ''
        app.children = []
    }

    // 查找、操作节点
    function fnOperateNode(id, val, dataList, type) {
        if (dataList && dataList.length) {
            for (let i = 0; i < dataList.length; i++) {
                if (dataList[i] && dataList[i].id == id) {
                    if (type == 'create') {
                        app.$set(dataList[i].children, dataList[i].children.length, val)
                        fnGeneratorTreeNode(app.orgDataList)
                    } else if (type == 'detail') {
                        app.detail = dataList[i]
                    } else if (type == 'modify') {
                        dataList[i] = val
                        fnGeneratorTreeNode(app.orgDataList)
                    } else if (type == 'delete') {
                        dataList.splice(i,1)
                        console.log(app.orgDataList)
                        fnGeneratorTreeNode(app.orgDataList)
                    }
                } else if (dataList[i].children && dataList[i].children.length) {
                    fnOperateNode(id, val, dataList[i].children, type)
                }
            }
        }
    }

    // 悬浮选中ID
    function fnSetHoverId(id) {
        app.hoverId = id
    }

    // 移除悬浮选中ID
    function fnUnsetHoverId() {
        app.hoverId = ''
    }

    // 生成根节点 html
    function fnGeneratorTreeNode(dataList) {
        app.treeHtml = ''
        dataList.forEach((item) => {
            if (item) {
                app.treeHtml += '<div class="node"><div class="content"><span οnmοuseοver="fnSetHoverId(' + item.id + ')">' + item.label + '</span>';
                if (item.children && item.children.length) {
                    app.treeHtml += fnGeneratorLeafNode(item.children)
                }
                app.treeHtml += '</div></div>'
            }
        })
    }

    // 生成叶节点 html
    function fnGeneratorLeafNode(dataList) {
        let content = ''
        for (let i = 0; i < dataList.length; i++) {
            content += '<div class="node"><div class="content"><span οnmοuseοver="fnSetHoverId(' + dataList[i].id + ')">' + dataList[i].label + '</span>';
            if (dataList[i].children && dataList[i].children.length) {
                content += fnGeneratorLeafNode(dataList[i].children)
            }
            content += '</div></div>'
        }
        return content
    }

    fnGeneratorTreeNode(app.orgDataList)

</script>
<style>
    * {
        padding: 0;
        margin: 0;
    }

    html, body {
        width: 100%;
        height: 100%;
    }

    ul {
        list-style: none;
    }

    #app {
        width: 100%;
        height: 100%;
    }

    .box {
        width: 100%;
        height: 100%;
        background-color: #ffffff;
    }

    .menu {
        width: 100px;
        height: auto;
        position: fixed;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        border: 1px solid #000000;
        border-radius: 5px;
        background-color: #ffffff;
    }

    .menu .btn {
        width: 80px;
        height: 20px;
        padding: 10px;
        text-align: center;
    }

    .menu .btn:hover {
        background-color: black;
    }

    .menu .btn:hover span {
        color: #ffffff;
    }

    .tree {
        padding: 50px;
    }

    .node {
        padding-left: 20px;
        width: 100%;
        height: 100%;
        cursor: pointer;
    }

    .wrapper {
        width: 100%;
        height: 100%;
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 1000;
        background-color: black;
        opacity: 0.7;
        text-align: center;
    }

    .dialog {
        width: 320px;
        height: 300px;
        z-index: 1001;
        background-color: #ffffff;
        display: inline-block;
        vertical-align: middle;
        text-align: left;
    }

    .wrapper:after {
        height: 100%;
        width: 0px;
        content: "";
        display: inline-block;
        text-align: center;
        vertical-align: middle;
    }

    .form {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-items: start;
        justify-content: left;
        padding: 20px;
    }

    .form input {
        width: 280px;
        line-height: 25px;
        margin-bottom: 10px;
    }

    .form textarea {
        width: 280px;
    }

    button {
        width: 50px;
        height: 30px;
    }

    label {
        font-size: 14px;
    }

    .btn-group {
        margin-bottom: -1px;
    }
</style>
</html>

展示效果

右键显示操作菜单
在这里插入图片描述
弹窗
在这里插入图片描述

直接复制代码导致鼠标悬浮事件失效

在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值