Merge branch 'master' of http://47.97.1.152:5880/r/zy-asrs-master
|  |  |  | 
|---|
|  |  |  | import { Clipboard } from '@antv/x6-plugin-clipboard'; | 
|---|
|  |  |  | import { Stencil } from '@antv/x6-plugin-stencil'; | 
|---|
|  |  |  | import { History } from '@antv/x6-plugin-history' | 
|---|
|  |  |  | import { commonGraphPorts, commonGraphAttrs } from "./GraphConfig"; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import { Transform } from '@antv/x6-plugin-transform' | 
|---|
|  |  |  | import { commonGraphPorts, commonGraphAttrs, initGraphConnecting } from "./GraphConfig"; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | export const GraphComponent = React.forwardRef((props, ref) => { | 
|---|
|  |  |  | const container = useRef(null); | 
|---|
|  |  |  | 
|---|
|  |  |  | function initGrap() { | 
|---|
|  |  |  | ref.current = new Graph({ | 
|---|
|  |  |  | container: container.current, | 
|---|
|  |  |  | // width: document.documentElement.clientWidth, | 
|---|
|  |  |  | // height: document.documentElement.clientHeight, | 
|---|
|  |  |  | width: 200, | 
|---|
|  |  |  | height: 500, | 
|---|
|  |  |  | // grid: 1, | 
|---|
|  |  |  | connecting: { | 
|---|
|  |  |  | snap: true, | 
|---|
|  |  |  | createEdge() { | 
|---|
|  |  |  | return new Shape.Edge({ | 
|---|
|  |  |  | attrs: { | 
|---|
|  |  |  | line: { | 
|---|
|  |  |  | stroke: '#a0a0a0', | 
|---|
|  |  |  | strokeWidth: 1, | 
|---|
|  |  |  | targetMarker: { | 
|---|
|  |  |  | name: 'classic', | 
|---|
|  |  |  | size: 8, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | connector: 'smooth', | 
|---|
|  |  |  | allowMulti: true, | 
|---|
|  |  |  | allowPort: true, | 
|---|
|  |  |  | } | 
|---|
|  |  |  | width: document.documentElement.clientWidth, | 
|---|
|  |  |  | height: document.documentElement.clientHeight - 100, | 
|---|
|  |  |  | // width: 200, | 
|---|
|  |  |  | // height: 500, | 
|---|
|  |  |  | connecting: initGraphConnecting, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const graph = ref.current; | 
|---|
|  |  |  | 
|---|
|  |  |  | }), | 
|---|
|  |  |  | ) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.use( | 
|---|
|  |  |  | new Transform({ | 
|---|
|  |  |  | resizing: { | 
|---|
|  |  |  | enabled: true | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }), | 
|---|
|  |  |  | ) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | props.initHandle();//通知父组件初始化完成 | 
|---|
|  |  |  | return graph; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | stencilContainer.current.appendChild(stencil.container) | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const n1 = graph.createNode({ | 
|---|
|  |  |  | shape: "rect", | 
|---|
|  |  |  | width: 80, | 
|---|
|  |  |  | height: 40, | 
|---|
|  |  |  | label: "默认组件", | 
|---|
|  |  |  | attrs: commonGraphAttrs, | 
|---|
|  |  |  | ports: commonGraphPorts | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const n2 = graph.createNode({ | 
|---|
|  |  |  | 
|---|
|  |  |  | height: 40, | 
|---|
|  |  |  | label: "测试组件", | 
|---|
|  |  |  | attrs: commonGraphAttrs, | 
|---|
|  |  |  | ports: commonGraphPorts | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | stencil.load([n1, n2], 'group1') | 
|---|
|  |  |  | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.bindKey('ctrl+z', () => { | 
|---|
|  |  |  | graph.undo() | 
|---|
|  |  |  | if (graph.canUndo()) { | 
|---|
|  |  |  | graph.undo() | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return false | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.bindKey('ctrl+y', () => { | 
|---|
|  |  |  | graph.redo() | 
|---|
|  |  |  | if (graph.canRedo()) { | 
|---|
|  |  |  | graph.redo() | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return false | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | return false | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.on('node:mouseenter', ({ node }) => { | 
|---|
|  |  |  | const ports = document.querySelectorAll(".x6-port-body") | 
|---|
|  |  |  | for (let i = 0, len = ports.length; i < len; i += 1) { | 
|---|
|  |  |  | ports[i].style.visibility = 'visible' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.on('node:mouseleave', ({ node }) => { | 
|---|
|  |  |  | const ports = document.querySelectorAll(".x6-port-body") | 
|---|
|  |  |  | for (let i = 0, len = ports.length; i < len; i += 1) { | 
|---|
|  |  |  | ports[i].style.visibility = 'hidden' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return ( | 
|---|
|  |  |  | 
|---|
|  |  |  | import React, { useRef, useEffect } from "react"; | 
|---|
|  |  |  | import { Graph, Shape } from "@antv/x6"; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const commonGraphPorts = { | 
|---|
|  |  |  | groups: { | 
|---|
|  |  |  | 
|---|
|  |  |  | position: 'top', | 
|---|
|  |  |  | attrs: { | 
|---|
|  |  |  | circle: { | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#8f8f8f', | 
|---|
|  |  |  | r: 5, | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#5F95FF', | 
|---|
|  |  |  | strokeWidth: 1, | 
|---|
|  |  |  | fill: '#fff', | 
|---|
|  |  |  | style: { | 
|---|
|  |  |  | visibility: 'hidden', | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | 
|---|
|  |  |  | position: 'bottom', | 
|---|
|  |  |  | attrs: { | 
|---|
|  |  |  | circle: { | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#8f8f8f', | 
|---|
|  |  |  | r: 5, | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#5F95FF', | 
|---|
|  |  |  | strokeWidth: 1, | 
|---|
|  |  |  | fill: '#fff', | 
|---|
|  |  |  | style: { | 
|---|
|  |  |  | visibility: 'hidden', | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | 
|---|
|  |  |  | position: 'left', | 
|---|
|  |  |  | attrs: { | 
|---|
|  |  |  | circle: { | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#8f8f8f', | 
|---|
|  |  |  | r: 5, | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#5F95FF', | 
|---|
|  |  |  | strokeWidth: 1, | 
|---|
|  |  |  | fill: '#fff', | 
|---|
|  |  |  | style: { | 
|---|
|  |  |  | visibility: 'hidden', | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | 
|---|
|  |  |  | position: 'right', | 
|---|
|  |  |  | attrs: { | 
|---|
|  |  |  | circle: { | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#8f8f8f', | 
|---|
|  |  |  | r: 5, | 
|---|
|  |  |  | magnet: true, | 
|---|
|  |  |  | stroke: '#5F95FF', | 
|---|
|  |  |  | strokeWidth: 1, | 
|---|
|  |  |  | fill: '#fff', | 
|---|
|  |  |  | style: { | 
|---|
|  |  |  | visibility: 'hidden', | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | export { commonGraphPorts, commonGraphAttrs } | 
|---|
|  |  |  | const initGraphConnecting = { | 
|---|
|  |  |  | router: 'manhattan', | 
|---|
|  |  |  | connector: { | 
|---|
|  |  |  | name: 'rounded', | 
|---|
|  |  |  | args: { | 
|---|
|  |  |  | radius: 8, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | anchor: 'center', | 
|---|
|  |  |  | connectionPoint: 'anchor', | 
|---|
|  |  |  | allowBlank: false, | 
|---|
|  |  |  | snap: { | 
|---|
|  |  |  | radius: 20, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | createEdge() { | 
|---|
|  |  |  | return new Shape.Edge({ | 
|---|
|  |  |  | attrs: { | 
|---|
|  |  |  | line: { | 
|---|
|  |  |  | stroke: '#A2B1C3', | 
|---|
|  |  |  | strokeWidth: 2, | 
|---|
|  |  |  | targetMarker: { | 
|---|
|  |  |  | name: 'block', | 
|---|
|  |  |  | width: 12, | 
|---|
|  |  |  | height: 8, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | zIndex: 0, | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | validateConnection({ targetMagnet }) { | 
|---|
|  |  |  | return !!targetMagnet | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | export { commonGraphPorts, commonGraphAttrs, initGraphConnecting } | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | import React, { useRef, useEffect, useState } from "react"; | 
|---|
|  |  |  | import { Button, Drawer, Input } from 'antd'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const { TextArea } = Input; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | export const GraphDrawer = ({ graphRef, isReady }) => { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const [open, setOpen] = useState(false); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const [init, setInit] = useState(false); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const [nodeData, setNodeData] = useState(null); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const [codeContent,setCodeContent] = useState(null); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const showDrawer = (graph, node) => { | 
|---|
|  |  |  | setOpen(true); | 
|---|
|  |  |  | setNodeData(node); | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const onClose = (e) => { | 
|---|
|  |  |  | setOpen(false); | 
|---|
|  |  |  | setNodeData(null); | 
|---|
|  |  |  | console.log(codeContent); | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const textAreaChange = (e) => { | 
|---|
|  |  |  | setCodeContent(e.target.value); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | useEffect(() => { | 
|---|
|  |  |  | if (isReady) { | 
|---|
|  |  |  | const graph = graphRef.current; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!init) { | 
|---|
|  |  |  | graph.on("node:dblclick", ({ node }) => { | 
|---|
|  |  |  | console.log(node); | 
|---|
|  |  |  | showDrawer(graph, node); | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | setInit(true); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if(nodeData){ | 
|---|
|  |  |  | return ( | 
|---|
|  |  |  | <> | 
|---|
|  |  |  | <Drawer title={nodeData.label} onClose={onClose} open={open} size="large"> | 
|---|
|  |  |  | <p>ID:{nodeData.id}</p> | 
|---|
|  |  |  | <p>可执行代码:</p> | 
|---|
|  |  |  | <TextArea onChange={textAreaChange} rows={10} /> | 
|---|
|  |  |  | </Drawer> | 
|---|
|  |  |  | </> | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | import React, { useRef, useEffect } from "react"; | 
|---|
|  |  |  | import React, { useRef, useEffect, useState } from "react"; | 
|---|
|  |  |  | import { Button } from 'antd'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | export const GraphTools = ({ graphRef,isReady }) => { | 
|---|
|  |  |  | export const GraphTools = ({ graphRef, isReady }) => { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const exportData = () => { | 
|---|
|  |  |  | const graph = graphRef.current; | 
|---|
|  |  |  | if (graph) { | 
|---|
|  |  |  | if (isReady) { | 
|---|
|  |  |  | const data = graph.toJSON(); | 
|---|
|  |  |  | console.log(data); | 
|---|
|  |  |  | // 这里你可以将数据发送到服务器或保存到本地 | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return <button onClick={exportData}>导出数据</button>; | 
|---|
|  |  |  | return ( | 
|---|
|  |  |  | <> | 
|---|
|  |  |  | <Button type="primary" onClick={exportData}> | 
|---|
|  |  |  | 导出数据 | 
|---|
|  |  |  | </Button> | 
|---|
|  |  |  | </> | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | } | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | import React, { useRef, useEffect } from "react"; | 
|---|
|  |  |  | import { Button } from 'antd'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //右键菜单组件 | 
|---|
|  |  |  | export const RightMenu = ((props) => { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | useEffect(() => { | 
|---|
|  |  |  | if (props.isReady) { | 
|---|
|  |  |  | const graph = props.graphRef.current; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.on('blank:contextmenu', ({ e, x, y }) => { | 
|---|
|  |  |  | // 阻止浏览器的默认行为 | 
|---|
|  |  |  | e.preventDefault(); | 
|---|
|  |  |  | closeContextMenu() | 
|---|
|  |  |  | openContextMenu(e.clientX, e.clientY, graph); | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | graph.on('cell:mouseup blank:mouseup', closeContextMenu); | 
|---|
|  |  |  | document.body.addEventListener('click', closeContextMenu); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | function openContextMenu(x, y, graph) { | 
|---|
|  |  |  | // 创建你的自定义菜单元素 | 
|---|
|  |  |  | let menuElement = document.createElement('div'); | 
|---|
|  |  |  | menuElement.classList.add('my-context-menu'); | 
|---|
|  |  |  | menuElement.style.left = `${x}px`; | 
|---|
|  |  |  | menuElement.style.top = `${y}px`; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | let dataList = ['选择', '移动'] | 
|---|
|  |  |  | dataList.forEach((val) => { | 
|---|
|  |  |  | // 在这里填充你的菜单内容,例如 | 
|---|
|  |  |  | let menuItem = document.createElement('div'); | 
|---|
|  |  |  | menuItem.classList.add("right-menu-button") | 
|---|
|  |  |  | menuItem.textContent = val; | 
|---|
|  |  |  | menuItem.onclick = (e) => { | 
|---|
|  |  |  | // 在这里处理菜单项点击事件,例如你可以根据点击的菜单项进行不同的操作 | 
|---|
|  |  |  | if (e.target.textContent == "选择") { | 
|---|
|  |  |  | graph.disablePanning();//禁用移动 | 
|---|
|  |  |  | graph.enableRubberband();//开启框选 | 
|---|
|  |  |  | } else if (e.target.textContent == "移动") { | 
|---|
|  |  |  | graph.enablePanning();//开启移动 | 
|---|
|  |  |  | graph.disableRubberband();//禁用框选 | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | menuElement.append(menuItem); | 
|---|
|  |  |  | }) | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 最后,将菜单添加到文档中 | 
|---|
|  |  |  | document.body.append(menuElement); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | function closeContextMenu() { | 
|---|
|  |  |  | let menuElement = document.querySelector('.my-context-menu'); | 
|---|
|  |  |  | if (menuElement) { | 
|---|
|  |  |  | document.body.removeChild(menuElement); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | import { Graph, Shape } from "@antv/x6"; | 
|---|
|  |  |  | import { GraphComponent } from "../../components/Flow/GraphComponent"; | 
|---|
|  |  |  | import { GraphTools } from "../../components/Flow/GraphTools"; | 
|---|
|  |  |  | import { RightMenu } from "../../components/Flow/RightMenu"; | 
|---|
|  |  |  | import { GraphDrawer } from "../../components/Flow/GraphDrawer"; | 
|---|
|  |  |  | import './index.less'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | export default function () { | 
|---|
|  |  |  | 
|---|
|  |  |  | }, [ready]); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return ( | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <div className="stencil-app"> | 
|---|
|  |  |  | <GraphTools isReady={ready} graphRef={graphRef} /> | 
|---|
|  |  |  | <GraphComponent ref={graphRef} initHandle={initHandle} /> | 
|---|
|  |  |  | <RightMenu isReady={ready} graphRef={graphRef} /> | 
|---|
|  |  |  | <GraphDrawer isReady={ready} graphRef={graphRef} /> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | .stencil-app { | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | padding: 0; | 
|---|
|  |  |  | font-family: sans-serif; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .app-stencil { | 
|---|
|  |  |  | position: relative; | 
|---|
|  |  |  | width: 300px; | 
|---|
|  |  |  | border: 1px solid #f0f0f0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .app-content { | 
|---|
|  |  |  | flex: 1; | 
|---|
|  |  |  | height: 380px; | 
|---|
|  |  |  | margin-right: 8px; | 
|---|
|  |  |  | margin-left: 8px; | 
|---|
|  |  |  | box-shadow: 0 0 10px 1px #e9e9e9; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | padding: 0; | 
|---|
|  |  |  | font-family: sans-serif; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .app-stencil { | 
|---|
|  |  |  | position: relative; | 
|---|
|  |  |  | width: 300px; | 
|---|
|  |  |  | border: 1px solid #f0f0f0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .app-content { | 
|---|
|  |  |  | flex: 1; | 
|---|
|  |  |  | height: 380px; | 
|---|
|  |  |  | margin-right: 8px; | 
|---|
|  |  |  | margin-left: 8px; | 
|---|
|  |  |  | box-shadow: 0 0 10px 1px #e9e9e9; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .x6-node.node-active .x6-port .x6-port-body { | 
|---|
|  |  |  | visibility: visible; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .my-context-menu { | 
|---|
|  |  |  | width: 150px; | 
|---|
|  |  |  | // height: 100px; | 
|---|
|  |  |  | background: #fff; | 
|---|
|  |  |  | position: absolute; | 
|---|
|  |  |  | border-radius: 10px; | 
|---|
|  |  |  | overflow: hidden; | 
|---|
|  |  |  | border: 1px #000 solid; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .right-menu-button { | 
|---|
|  |  |  | background: #fff; | 
|---|
|  |  |  | padding: 5px 10px; | 
|---|
|  |  |  | color: #000; | 
|---|
|  |  |  | text-align: center; | 
|---|
|  |  |  | cursor: pointer; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .right-menu-button:hover { | 
|---|
|  |  |  | background: rgb(22,119,255); | 
|---|
|  |  |  | color: #fff; | 
|---|
|  |  |  | } | 
|---|