四、LogicFlow 自定义左侧菜单Menu

news2024/11/13 12:52:19

目录

    • 前文
    • LogicFlow 介绍
    • 实现基础界面框架
    • 实现左侧菜单组件
    • 将左侧菜单引入到demo组件中
    • 最后

在这里插入图片描述

前文

这篇相对来讲就稍微平凡了一点,只要有前端的一些基础就能够轻松完成上图中左侧的菜单,但是为了能够让前后文章能够连贯起来,所以还是要厚着脸皮再写一篇。

有人可能要问了,为啥不将图中的功能完全实现呢,那是因为会直接导致篇幅过长,不利于阅读,思路不够清晰。

下一章节将实现 自定义节点

LogicFlow 介绍

LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端研发自定义开发各种逻辑编排场景,如流程图、ER图、BPMN流程等。在工作审批配置、机器人逻辑编排、无代码平台流程配置都有较好的应用。

实现基础界面框架

在这里插入图片描述

<template>
    <div class="demo-wrp">
        <div class="demo-nemu"></div>
        <div class="demo-container">
            <div class="demo-control-wrp"></div>
            <div class="demo-canvas-wrp" ref="diagram"></div>
        </div>
    </div>
</template>

<script>
// 引入LogicFlow核心包
import LogicFlow from '@logicflow/core';
import '@logicflow/core/dist/style/index.css';

export default ({
    name: 'demo',
    data () {
        return {
            // 模拟数据
            mockData: {
                nodes: [
                    { id: "1", type: "rect", x: 100, y: 100, text: "节点1" },
                    { id: "2", type: "circle", x: 300, y: 100, text: "节点2" },
                ],
                edges: [
                    {
                    sourceNodeId: "1",
                    targetNodeId: "2",
                    type: "polyline",
                    text: "连线",
                    startPoint: {
                        x: 140,
                        y: 100,
                    },
                    endPoint: {
                        x: 250,
                        y: 100,
                    },
                    },
                ],
            }
        }
    },

    mounted () {

        // 创建实例
        const lf = new LogicFlow({
            container: this.$refs.diagram,
            // ... 其他的一些配置
        })

        /* 
            开启渲染
            如果不要模拟数据,直接使用 lf.render() 即可。
        **/
        lf.render(this.mockData);

        // 渲染到视图中心为止,否则在左上角显示
        lf.translateCenter();
    }
})

</script>


<style scoped lang="less">
// 定义操控区域高度
@HEADER_HEIGHT: 50px;
// 定义菜单和操控区域背景色
@BG_COLOR: #f3f3f3;

.demo-wrp{
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;

    .demo-nemu{
        width: 200px;
        height: 100%;
        overflow-y: auto;
        background-color: @BG_COLOR;
        border-right: 1px solid #ddd;

        &::-webkit-scrollbar {
            width: 4px;
            background-color: #eeeeee;
        }

        &::-webkit-scrollbar-track {
            box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.01);
            border-radius: 0;
            background: rgba(0, 0, 0, 0);
        }

        &::-webkit-scrollbar-thumb {
            border-radius: 40px;
            box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.3);
            background: rgba(0, 0, 0, 0);
        }
    }

    .demo-container{
        flex: 1;
        height: 100%;
        background-color: @BG_COLOR;


        .demo-control-wrp{
            width: 100%;
            height: @HEADER_HEIGHT;
            display: flex;
            align-items: center;
            justify-content: flex-end;
            border-bottom: 1px solid #ddd;
            padding: 0 20px;
        }
        .demo-canvas-wrp{
            width: 100%;
            height: calc(100% - @HEADER_HEIGHT);
        }
    }
}

</style>

实现上面的界面布局还是相当简单的,如果对样式感觉很困惑,那就只有多敲多练了。

另外根据如上代码在 vscode 中,样式部分可能会标红,不影响使用,代码也是生效的。

在这里插入图片描述

如果觉得看着不顺眼那也很简单,只需要在同级目录下创建一个 less 格式的文件,然后把样式拷贝进去,再将这个 less 文件引入到当前使用的组件中,如下所示:

<style lang="less" scoped>
	@import url('./index.less');
</style>

实现左侧菜单组件

基础的界面框架已经搭建好了,那么接下来就要实现左侧菜单了,为了让界面结构逻辑更加的清晰,建议是将菜单部分单独作为一个组件进行使用。

在 demo 目录下创建 components 目录,专门用来处理 LogicFlow 相关的组件,到时候如需其他项目也要使用的时候,直接拷贝过去就能投产,极大便利降低使用成本。

<template>
    <ul class="diagram-sidebar">
        <li v-for="groupItem in leftDataList" :key="groupItem.key">
            <h1 class="node-category-title">{{ groupItem.groupName }}</h1>
            <template v-if="Array.isArray(groupItem.nodes) && groupItem.nodes.length > 0">
                <div 
                    v-for="item in groupItem.nodes" 
                    :key="item.type" 
                    class="left-bar-item" 
                    :class="getClassFn"  
                    :style="getItemStyleFn(item)" 
                    @mousedown="dragInNode(item.type)"
                >
                    <img class="icon" :src="item.icon" alt="">
                    <p class="name" :style="`color:${item.borderColor};`">{{item.name}}</p>
                </div>
            </template>
        </li>
    </ul>
</template>

<script>
import { InitNodeData, CanNotEdit } from './NodeEnum';
export default ({
    name: 'leftMenu',
    props: {
        taskDetail: Object,
    },
    data() {
        return {
            leftDataList: [
                {
                    groupName: '分组-1',
                    key: 'marketing',
                    nodes: [
                        {
                            icon: require('../assets/lfCanvas/leftIcon/singleCrowd.svg'),
                            type: 'SINGLE_CROWD',
                            borderColor: 'rgba(71, 98, 254, 1)',
                            backgroundColor: 'rgba(71, 98, 254, 0.1)',
                            name: '单个信息',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/batchCrowd.svg'),
                            type: 'BATCH_CROWD',
                            borderColor: 'rgba(71, 98, 254, 1)',
                            backgroundColor: 'rgba(71, 98, 254, 0.1)',
                            name: '批量信息',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/ruleCrowd.svg'),
                            type: 'RULE_CROWD',
                            borderColor: 'rgba(71, 98, 254, 1)',
                            backgroundColor: 'rgba(71, 98, 254, 0.1)',
                            name: '信息规则',
                        },
                    ],
                },
                {
                    groupName: '分组-2',
                    key: 'target',
                    nodes: [
                        {
                            icon: require('../assets/lfCanvas/leftIcon/goalCrowd.svg'),
                            type: 'GOAL_CROWD',
                            borderColor: 'rgba(64, 158, 255, 1)',
                            backgroundColor: 'rgba(64, 158, 255, 0.1)',
                            name: '目标',
                        },
                    ],
                },
                {
                    groupName: '分组-3',
                    key: 'compute',
                    nodes: [
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-merge.svg'),
                            type: 'MERGE',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '合并',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-split.svg'),
                            type: 'SPLIT',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '拆分',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-unique.svg'),
                            type: 'UNIQUE',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '排重',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-intersection.svg'),
                            type: 'AND',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '交集',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-exclude.svg'),
                            type: 'EXCLUDE',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '排除',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-spread.svg'),
                            type: 'SPREAD',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '智能扩散',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/compute/icon-compute-sort.svg'),
                            type: 'SORT',
                            borderColor: 'rgba(255, 180, 30, 1)',
                            backgroundColor: 'rgba(255, 180, 30, 0.15)',
                            name: '高能排序',
                        },
                    ],
                },
                {
                    groupName: '分组-4',
                    key: 'touch',
                    nodes: [
                        {
                            icon: require('../assets/lfCanvas/leftIcon/dongdong.svg'),
                            type: 'DONGDONG',
                            borderColor: 'rgba(0, 200, 100, 1)',
                            backgroundColor: 'rgba(0, 200, 100, 0.1)',
                            name: '消息',
                        },
                        {
                            icon: require('../assets/lfCanvas/leftIcon/sms.svg'),
                            type: 'SMS',
                            borderColor: 'rgba(0, 200, 100, 1)',
                            backgroundColor: 'rgba(0, 200, 100, 0.1)',
                            name: '短信',
                        },
                    ],
                },
            ],
        }
    },
    computed: {

        // 拖拽和禁用拖拽按钮状态
        getClassFn(){
            return this.canDrag ? 'cursor-not-allowed' : 'cursor-pointer'
        },

        // 判断是否可被拖拽(先注释)
        canDrag() {
            // return this.canvasType === 'detail' || CanNotEdit.includes(this.taskDetail?.canvasStatus?.toString());
        },
        
        canvasType() {
            const QUERY_TYPE = this.$router.history.current.query.type;
            console.log('QUERY_TYPE::', QUERY_TYPE);
            return QUERY_TYPE;
        },
        
    },
    mounted() {

    },
    methods: {
        getMenuIconObj(item) {
            return {
                icon: item.icon,
                name: item.name
            }
        },
        // 动态设置样式
        getItemStyleFn(item){
            return `border: 1px solid ${item.borderColor};background-color:${item.backgroundColor};`
        },
		// 数据按下事件,主要是获取菜单的type类型
        dragInNode(type) {
            const that = this;
            console.log('dragInNode', that.canDrag, that.taskDetail);
            if (that.canDrag) return;

			
            // that.$emit('dragInNode', {
            //     type,
            //     properties: {
            //         ...InitNodeData[type],
            //     },
            // });
        },
    }
})
</script>

<style lang="less" scoped>
.diagram-sidebar {
    user-select: none;
    flex-basis: 200px;
    padding: 13px 25px;

    .node-category-title {
        font-family: PingFang SC;
        font-size: 14px;
        font-weight: 600;
        line-height: 22px;
        text-align: left;
        margin-bottom: 12px;
    }

    .cursor-pointer {
        cursor: pointer;
    }

    .cursor-not-allowed {
        cursor: not-allowed;
    }


    .left-bar-item{
        width: 140px;
        height: 38px;
        border-radius: 8px;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        gap: 8px;
        margin-bottom: 12px;
        padding-left: 24px;
        .icon{
            width: 16px;
            height: 16px;
        }
        .name{
            font-family: PingFang SC;
            font-size: 14px;
            font-weight: 400;
            line-height: 22px;
            text-align: left;
        }
    }
}
</style>

实现效果如下:
在这里插入图片描述

这样就实现了一个自定义的左侧菜单,这样可以根据自己的需要手动引入到对应的组件中进行使用,但是需要注意一点的是在 script标签 中引入的外部文件是否存在,地址是否正确。

将左侧菜单引入到demo组件中

<template>
    <div class="demo-wrp">
        <div class="demo-nemu">
            <LeftMenu :taskDetail="taskDetail" />
        </div>
        <div class="demo-container">
            <div class="demo-control-wrp"></div>
            <div class="demo-canvas-wrp" ref="diagram"></div>
        </div>
    </div>
</template>

<script>

// 引入LogicFlow核心包
import LogicFlow from '@logicflow/core';
import '@logicflow/core/dist/style/index.css';

// 引入组件
import LeftMenu from './components/LeftMenu';


export default ({
    name: 'demo',
    data () {
        return {
            // ...
            
       		taskDetail: {},
       		
            // ...
        }
    },

    components: {
        LeftMenu,
    },

    // 其他...
})

</script>


最后

关于自定义左侧菜单到这里也就结束了,只要会点 Vue 都能够看懂,一点都不难,所以也没啥好讲的。

下一篇将讲解如何将左侧的按钮拖拽到右侧的画布。

这一篇到此结束,拜拜。

在这里插入图片描述

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

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

相关文章

一文彻底搞懂ZooKeeper选举机制

原文阅读&#xff1a;【巨人肩膀社区博客分享】一文彻底搞懂ZooKeeper选举机制 1. ZooKeeper 集群 ZooKeeper 是一个高性能分布式的开源协调服务&#xff0c;用于构建分布式应用程序和服务。 一个 ZooKeeper 集群通常由多个 ZooKeeper 服务器组成&#xff0c;这些服务器分布在…

C语言基础(二十三)

在C语言中&#xff0c;修改链表中的数据涉及遍历链表以找到要修改的元素&#xff0c;然后更新该元素的值。链表是一种动态数据结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含数据部分和指向列表中下一个节点的指针&#xff08;双向链表&#xff0c;还会有指向前一…

<Rust>egui学习之小部件(四):如何在窗口中添加滑动条部件?

前言 本专栏是关于Rust的GUI库egui的部件讲解及应用实例分析&#xff0c;主要讲解egui的源代码、部件属性、如何应用。 环境配置 系统&#xff1a;windows 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;egui、eframe 概述 本文是本专栏的第四篇博…

Ubuntu 24.04 安装 intel 编译器

目录 1.采用用户界面 GUI 安装英特尔基本工具包 Intel oneAPI Base Toolkit 1.1 下载离线英特尔基本工具包 1.2 安装英特尔基本工具包 1.3 英特尔基本工具包 Intel oneAPI Base Toolkit 环境设置 2.安装英特尔基本工具包 Intel HPC Toolkit 2.1 下载离线英特尔高性能计算…

智能座舱高通8155摄像头方案

高通汽车开发平台 &#xff08;ADP&#xff09;基于8155的多媒体硬件框图如下所示&#xff1a;有4个4路CSI摄像头处理通路&#xff0c;2个4路DSI屏幕处理通路&#xff0c;1个DisplayPort。 基于摄像头的详细方案如下&#xff1a;可以处理4路MAX9296解串后信号。 再深入细化基于…

Java10 集合

集合 集合集合接口等级&#xff1a;Collection&#xff1a;单例集合接口,将数据一个一个存储&#xff0c;存储的是值。ArrayList类&#xff1a;泛型集合Linkedlist集合&#xff1a;Vector集合&#xff1a;Stack集合&#xff1a;Vetor的子类 Set接口&#xff1a;存储是无序的&am…

【使用 Python 进行截图的两种方法】

在 Python 中&#xff0c;可以使用 pyautogui 和 Pillow 进行截图 使用 pyautogui 进行截图时&#xff0c;其提供了方便的函数。例如&#xff0c;使用 pyautogui.screenshot() 函数可以获取整个屏幕的截图&#xff0c;该函数返回一个包含屏幕截图的图像对象。如果不想截取整个…

最大噪音值甚至受法规限制,如何基于LBM算法有效控制风扇气动噪音

风扇的气动噪声 在工业设备行业&#xff0c;最大噪音值受法规限制。在很多使用风扇冷却的设备上&#xff0c;风扇噪声通常是这些设备工作噪声的最大贡献量。而在家电民用行业&#xff0c;例如空调、空气净化器、油烟机等&#xff0c;其噪音大小直接关系到用户的体验感受&#x…

从零开始掌握容器技术:Docker的奇妙世界

容器技术在当今的云计算和软件开发领域中扮演着越来越重要的角色。如果你是一名计算机专业的学生或从事IT行业的从业者&#xff0c;可能已经听说过Docker这个词。它在软件开发、部署、运维等环节中大放异彩&#xff0c;但对于刚接触这个概念的朋友来说&#xff0c;可能还是有些…

【乐企】有关乐企能力测试接口对接(详细)

1、申请密钥 2、验证本地服务器与乐企服务器的连通性 乐企服务器生产和测试域名均为&#xff1a;https://lqpt.chinatax.gov.cn:8443。开发者可以在“能力中心”查看基础公用能力详情&#xff0c;按照能力接入和开发指引完成接口对接&#xff0c;验证服务器连通性和证书配置正确…

给一个web网站,如何开展测试?

前言 Web测试是指针对Web应用程序(网站或基于Web的系统)进行的测试活动&#xff0c;以确保其质量、性能、安全性、可用性和兼容性等方面符合预期标准。Web测试涵盖了从前端用户界面(UI)到后端逻辑和数据库的各个方面&#xff0c;确保Web应用程序在不同环境和条件下都能正常运行…

参会投稿 | 第三届先进传感与智能制造国际学术会议(ASIM 2024)

第三届先进传感与智能制造国际会议&#xff08;The 3rd International Conference on Advanced Sensing, Intelligent Manufacturing&#xff09;&#xff0c;由江汉大学、西安交通大学和山东大学主办&#xff0c;由江西省机械工程学会、东华理工大学机械与电子工程学院等联合协…

Hibernate 批量插入速度慢的原因和解决方法

由于业务需要一次性连续写入超过10k条以上的新数据&#xff0c;当对象超过10个成员变量以后&#xff0c;整个写入过程居然需要长达35秒&#xff0c;这个速度是不能接受的&#xff0c;故此研究了一下怎么开启Hibernate批量写入的功能。 我这边使用的是Hibernate 5.6.15 在网上…

推动光模块技术发展:从400G、800G到1.6T

随着数据通信领域的持续发展&#xff0c;对于更快、更高传输速率的需求也在不断增长。作为现代数据传输的基石&#xff0c;光模块技术不断进步以满足这一需求。其中一项重大进展是网络速率从400G提升到800G&#xff0c;并将向1.6T继续发展。让我们深入探讨这些技术的演变&#…

Java语言程序设计基础篇_编程练习题***17.9 (地址簿)

目录 题目&#xff1a;***17.9 (地址簿) 习题思路 代码示例 结果展示 题目&#xff1a;***17.9 (地址簿) 编写程序用于存储、返回、增加&#xff0c;以及更新如图 17-20 所示的地址薄。使用固定长度的字符串来存储地址中的每个属性。使用随机访问文件来读取和写人一个地址…

刚刚认证!网络主播成为国家新职业,易播易赚打造打造职业入门全新模式

近期&#xff0c;人力资源和社会保障部会同国家市场监督管理总局、国家统计局日前增设网络主播为国家新职业&#xff0c;这标志着网络主播的职业身份在“国家确定职业分类”上首次得以确立。 据人社部此前印发的《关于加强新职业培训工作的通知》表示&#xff0c;新职业从业者可…

代码随想录算法训练营第二十三天| 39. 组合总和 40.组合总和II 131.分割回文串

目录 一、LeetCode 39. 组合总和思路&#xff1a;C代码 二、LeetCode 40.组合总和II思路C代码 三、LeetCode 131.分割回文串思路C代码 总结 一、LeetCode 39. 组合总和 题目链接&#xff1a;LeetCode 39. 组合总和 文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;带你学…

直播平台直播API集成之快手篇

前言: 本篇我们来介绍如何使用快手 的直播API创建直播。 准备工作: 1、你首先得有个快手账号; 2、创建快手应用,填写应用审核信息,等待应用创建审核通过,应用成功创建后在开发与上线前还要提前做好API权限申请,如果你只需要获取用户基本信息,以及得到直播API的访问权限…

Python | Leetcode Python题解之第377题组合总和IV

题目&#xff1a; 题解&#xff1a; class Solution:def combinationSum4(self, nums: List[int], target: int) -> int:dp [1] [0] * targetfor i in range(1, target 1):for num in nums:if num < i:dp[i] dp[i - num]return dp[target]

合宙LuatOS产品规格书——Air700EMQ

Air700EMQ是合宙通信的LTE Cat.1bis通信模块&#xff0c; 依托移芯EC716E平台&#xff0c;支持先进的LTE 3GPP Rel.13技术。 主要特点如下&#xff1a; 1. 技术平台与标准支持&#xff1a; Air700EMQ采用移芯EC716E平台&#xff0c;基于先进的LTE技术。支持LTE 3GPP Releas…