liuqiao 1 年間 前
コミット
d0bc3e7952

+ 2 - 1
index.html

@@ -5,7 +5,8 @@
     <!-- <link rel="icon" href="/assets/logo.png" /> -->
     <link rel="icon" href="favicon.ico">
     <!-- <link rel="shortcut icon" type="image/x-icon" href="<%= BASE_URL %>favicon.ico" />    -->
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
+ 
     <title></title>
   </head>
   <body>

+ 237 - 0
package-lock.json

@@ -11,6 +11,12 @@
         "@element-plus/icons": "^0.0.11",
         "@element-plus/icons-vue": "^2.1.0",
         "@kitware/vtk.js": "^29.7.3",
+        "@vue-flow/background": "^1.3.0",
+        "@vue-flow/controls": "^1.1.2",
+        "@vue-flow/core": "^1.37.1",
+        "@vue-flow/minimap": "^1.5.0",
+        "@vue-flow/node-resizer": "^1.4.0",
+        "@vue-flow/node-toolbar": "^1.1.0",
         "axios": "^1.5.0",
         "echarts": "^5.4.3",
         "element-plus": "^2.3.14",
@@ -2950,6 +2956,160 @@
         "@volar/language-core": "1.10.1"
       }
     },
+    "node_modules/@vue-flow/background": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@vue-flow/background/-/background-1.3.0.tgz",
+      "integrity": "sha512-fu/8s9wzSOQIitnSTI10XT3bzTtagh4h8EF2SWwtlDklOZjAaKy75lqv4htHa3wigy/r4LGCOGwLw3Pk88/AxA==",
+      "peerDependencies": {
+        "@vue-flow/core": "^1.23.0",
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/@vue-flow/controls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@vue-flow/controls/-/controls-1.1.2.tgz",
+      "integrity": "sha512-6dtl/JnwDBNau5h3pDBdOCK6tdxiVAOL3cyruRL61gItwq5E97Hmjmj2BIIqX2p7gU1ENg3z80Z4zlu58fGlsg==",
+      "peerDependencies": {
+        "@vue-flow/core": "^1.23.0",
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/@vue-flow/core": {
+      "version": "1.37.1",
+      "resolved": "https://registry.npmjs.org/@vue-flow/core/-/core-1.37.1.tgz",
+      "integrity": "sha512-gObhagpoxscJ0sc39NBdil3/nJI0f3P0uoP18FXymPh1Xw39DW9pZ0/qNrJo9IN+c0zoOhZbAhbjXtGGrifpDg==",
+      "dependencies": {
+        "@vueuse/core": "^10.5.0",
+        "d3-drag": "^3.0.0",
+        "d3-selection": "^3.0.0",
+        "d3-zoom": "^3.0.0"
+      },
+      "peerDependencies": {
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/@vue-flow/core/node_modules/@types/web-bluetooth": {
+      "version": "0.0.20",
+      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
+      "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
+    },
+    "node_modules/@vue-flow/core/node_modules/@vueuse/core": {
+      "version": "10.11.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.0.tgz",
+      "integrity": "sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.20",
+        "@vueuse/metadata": "10.11.0",
+        "@vueuse/shared": "10.11.0",
+        "vue-demi": ">=0.14.8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vue-flow/core/node_modules/@vueuse/core/node_modules/vue-demi": {
+      "version": "0.14.9",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.9.tgz",
+      "integrity": "sha512-dC1TJMODGM8lxhP6wLToncaDPPNB3biVxxRDuNCYpuXwi70ou7NsGd97KVTJ2omepGId429JZt8oaZKeXbqxwg==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue-flow/core/node_modules/@vueuse/metadata": {
+      "version": "10.11.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.0.tgz",
+      "integrity": "sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vue-flow/core/node_modules/@vueuse/shared": {
+      "version": "10.11.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.0.tgz",
+      "integrity": "sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==",
+      "dependencies": {
+        "vue-demi": ">=0.14.8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vue-flow/core/node_modules/@vueuse/shared/node_modules/vue-demi": {
+      "version": "0.14.9",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.9.tgz",
+      "integrity": "sha512-dC1TJMODGM8lxhP6wLToncaDPPNB3biVxxRDuNCYpuXwi70ou7NsGd97KVTJ2omepGId429JZt8oaZKeXbqxwg==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue-flow/minimap": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@vue-flow/minimap/-/minimap-1.5.0.tgz",
+      "integrity": "sha512-JhxXDF+8uTc7sgkZHDIvFpHqSl4wsK9xp8Kz5OHwNcXlgGcwqj4yad6jcc1B6bGxm+huESpNmoPotQbpMn6rVw==",
+      "dependencies": {
+        "d3-selection": "^3.0.0",
+        "d3-zoom": "^3.0.0"
+      },
+      "peerDependencies": {
+        "@vue-flow/core": "^1.23.0",
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/@vue-flow/node-resizer": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@vue-flow/node-resizer/-/node-resizer-1.4.0.tgz",
+      "integrity": "sha512-S52MRcSpd6asza8Cl0bKM2sHGrbq7vBydKHDuPdoTD+cvjNX6XF4LSiPZOuzExePI6b+O6dg2EZ1378oOLGFpA==",
+      "dependencies": {
+        "d3-drag": "^3.0.0",
+        "d3-selection": "^3.0.0"
+      },
+      "peerDependencies": {
+        "@vue-flow/core": "^1.23.0",
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/@vue-flow/node-toolbar": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@vue-flow/node-toolbar/-/node-toolbar-1.1.0.tgz",
+      "integrity": "sha512-6RVDHgY+x8m1cXPaEkqPa/RMR90AC1hPHYBK/QVh8k6lJnFPgwJ9PSiYoC4amsUiDK0mF0Py+PlztLJY1ty+4A==",
+      "peerDependencies": {
+        "@vue-flow/core": "^1.12.2"
+      }
+    },
     "node_modules/@vue/compiler-core": {
       "version": "3.3.4",
       "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
@@ -3866,6 +4026,34 @@
         "node": ">=12"
       }
     },
+    "node_modules/d3-dispatch": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+      "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-drag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
+      "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
+      "dependencies": {
+        "d3-dispatch": "1 - 3",
+        "d3-selection": "3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-ease": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+      "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/d3-format": {
       "version": "3.1.0",
       "resolved": "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.0.tgz",
@@ -3900,6 +4088,14 @@
         "node": ">=12"
       }
     },
+    "node_modules/d3-selection": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
+      "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/d3-time": {
       "version": "3.1.0",
       "resolved": "https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz",
@@ -3922,6 +4118,47 @@
         "node": ">=12"
       }
     },
+    "node_modules/d3-timer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+      "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-transition": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
+      "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
+      "dependencies": {
+        "d3-color": "1 - 3",
+        "d3-dispatch": "1 - 3",
+        "d3-ease": "1 - 3",
+        "d3-interpolate": "1 - 3",
+        "d3-timer": "1 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "peerDependencies": {
+        "d3-selection": "2 - 3"
+      }
+    },
+    "node_modules/d3-zoom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
+      "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
+      "dependencies": {
+        "d3-dispatch": "1 - 3",
+        "d3-drag": "2 - 3",
+        "d3-interpolate": "1 - 3",
+        "d3-selection": "2 - 3",
+        "d3-transition": "2 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/dayjs": {
       "version": "1.11.10",
       "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz",

+ 6 - 0
package.json

@@ -14,6 +14,12 @@
     "@element-plus/icons": "^0.0.11",
     "@element-plus/icons-vue": "^2.1.0",
     "@kitware/vtk.js": "^29.7.3",
+    "@vue-flow/background": "^1.3.0",
+    "@vue-flow/controls": "^1.1.2",
+    "@vue-flow/core": "^1.37.1",
+    "@vue-flow/minimap": "^1.5.0",
+    "@vue-flow/node-resizer": "^1.4.0",
+    "@vue-flow/node-toolbar": "^1.1.0",
     "axios": "^1.5.0",
     "echarts": "^5.4.3",
     "element-plus": "^2.3.14",

+ 5 - 2
src/main.js

@@ -7,11 +7,14 @@ import $ from 'jquery'
 import ElementUI from 'element-plus'
 import { createPinia } from 'pinia'
 import 'element-plus/theme-chalk/index.css' // 引入整个Element样式
-import './style/index.css' // 引入整个Element样式
-import '@/utils/flexible'
+// import './style/index.css' // 引入整个Element样式
+import './style/index.css' 
+// import '@/utils/flexible'
 import "normalize.css/normalize.css";//重置样式
 import directive from '@/utils/directive'
 import {registerEcharts} from "@/plugins/echarts"
+import'@vue-flow/core/dist/style.css'
+import '@vue-flow/core/dist/theme-default.css';
 
 // import mitt from 'mitt'
 

+ 2 - 3
src/main.ts

@@ -3,15 +3,14 @@ import './style.css'
 import App from './App.vue'
 //1、route
 import router from '@/router/index'
-
-
 //2、pinia
 import pinia from '@/store'
 
 //3、element-plus
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'
-import './style/index.css' // 引入整个Element样式
+import './style/index.css' // 
+//import './style/style.css'
 import "normalize.css/normalize.css";//重置样式
 import '@/js/lindex.js'
 //4、引入echarts

+ 18 - 0
src/router/index.js

@@ -13,6 +13,24 @@ const router = createRouter({
               title: '主页'
           },   
       },
+      {
+        path: '/vueflow',
+        name:'vueflow',
+        component: () => import('@/views/vueflow/index.vue'),
+        meta:{
+            keepAlive:false, // 需要缓存
+            title: 'vueflow'
+        },   
+    },
+    {
+      path: '/demo',
+      name:'demo',
+      component: () => import('@/views/vueflow/demo.vue'),
+      meta:{
+          keepAlive:false, // 需要缓存
+          title: 'vueflow'
+      },   
+  },
         
     ]
 })

+ 51 - 0
src/style/index.css

@@ -477,4 +477,55 @@ margin-top: -6px;
 }
 button:focus, button:focus-visible{
   outline:none;
+}
+
+/* Webkit内核浏览器(Chrome、Safari等)*/
+::-webkit-scrollbar {
+  width: 4px;
+  /* 设置滚动条宽度 */
+  background-color: #dcdfe6;
+  /* 设置滚动条背景颜色 */
+}
+
+/* 滑块样式 */
+::-webkit-scrollbar-thumb {
+  border-radius: 2px;
+  /* 设置滑块边角半径 */
+  background-color:#eee ;
+  /* 设置滑块背景颜色 */
+}
+
+/* 滑块在hover状态时的样式 */
+::-webkit-scrollbar-thumb:hover {
+  background-color: #dcdfe6;
+  /* 设置滑块在hover状态下的背景颜色 */
+}
+
+/* 滚动条轨道样式 */
+::-webkit-scrollbar-track {
+  background-color: #dcdfe6;
+  /* 设置滚动条轨道背景颜色 */
+}
+.el-input__inner{
+  --el-input-inner-height: calc(var(--el-input-height, .1667rem) - .0104rem) !important;
+}
+.left_main  .el-tabs__item {
+  color: #1A1A1A;
+}
+.panetab .el-image {
+
+  width: 60px;
+  vertical-align: middle;
+  padding: 10px;
+}
+.ve_menu_logo{
+text-align: left;
+}
+.lefttext .el-form-item__label{
+  text-align: left !important;
+  justify-content: flex-start !important;
+}
+.el-dialog__body{
+  max-height: 730px;
+  overflow-y: auto;
 }

+ 545 - 0
src/style/style.css

@@ -0,0 +1,545 @@
+/* reset.css */
+html {
+    box-sizing: border-box; /* 统一盒模型计算方式 */
+    font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
+    'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
+}
+*, *::before, *::after {
+    margin: 0;
+    padding: 0;
+    box-sizing: inherit; /* 继承上级元素的盒模型计算方式 */
+}
+body {
+    font-family: Arial, sans-serif; /* 设定基本字体族 */
+    font-family: '微软雅黑', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
+    'Microsoft YaHei', Arial, sans-serif;
+    line-height: 1.5; /* 行高 */
+}
+h1, h2, h3, h4, h5, h6 {
+    font-weight: normal; /* 取消标题标签的加粗效果 */
+}
+a {
+    text-decoration: none; /* 去除链接下划线 */
+    color: #007bff; /* 设定颜色 */
+}
+ul, ol,li {
+    list-style: none; /* 清除列表项符号 */
+
+}
+img {
+    max-width: 100%; /* 图片最大宽度自动调整到容器尺寸 */
+    height: auto; /* 保持原比例 */
+}
+button {
+    cursor: pointer; /* 改变光标形状为手指 */
+    background: transparent; /* 按钮无背景色 */
+    outline: none; /* 移除点击时的边框 */
+    border: none; /* 移除边框 */
+}
+input[type="text"], input[type="password"] {
+    appearance: none; /* 移除输入框默认外观 */
+    -webkit-appearance: none; /* Safari/Chrome特定属性 */
+    -moz-appearance: none; /* Firefox特定属性 */
+    border: none; /* 移除边框 */
+    outline: none; /* 移除点击时的边框 */
+    background: none; /* 输入框无背景色 */
+}
+img{
+    vertical-align: middle; 
+}
+/* 改 el-dialog的默认样式*/
+.el-header{
+    padding: 0;
+    --el-header-height:auto;
+}
+.el-main{
+    --el-main-padding: 0;;  
+}
+.heder_tabs{
+ 
+  --el-main-padding: 0 .1042rem!important;  
+}
+.heder_tabs .el-tabs__header{
+    padding: 0 .1042rem;
+    background-color:#2267B1; 
+}
+.ve_logo_img .el-image{
+    padding: 5px;
+}
+.heder_tabs .el-tabs__item{
+    width: 0.625rem;
+    height: .2083rem;
+}
+body{
+    width: 100%;
+    height: 100vh;
+    background-color:rgba(123, 176, 232, 0.1);
+}
+.heder_tabs .el-tabs__item.is-active{
+    background-color: #fff;
+    border-radius: .0521rem .0521rem 0px 0px;
+    color: #2267B1 ;
+}
+.el-tabs--card>.el-tabs__header .el-tabs__item,.el-tabs--card>.el-tabs__header .el-tabs__nav{
+    border: none;
+}
+.el-tabs__item{
+    color: #fff;
+    font-weight: bold;
+    font-size: .0729rem;
+}
+.imgzong {
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: flex;
+    overflow: auto;
+    white-space: nowrap;
+    background-color: #fff;
+    padding: 0 20px;
+}
+.imgzong .listitem {
+    width: auto;
+    height: .4792rem;
+     margin: .026rem 0; 
+    padding: .0104rem .0677rem .0104rem .0677rem;
+    position: relative;
+  
+}
+.imgzong .listitem::before{
+    content: '';
+    width: .0052rem ;
+    height: 0.4792rem;
+    position: absolute;
+    right: 0;
+    background-color:rgba(34,103,177,.2);
+
+}
+.activeOrange {
+    background-color: rgba(255, 255, 255, 0.3);
+    border: 2px solid #fff;
+    border-radius: 5px;
+    box-sizing: border-box;
+  }
+  /* .imgzong  .listitem{
+    border-right:1px solid rgba(34,103,177,0.2);
+  } */
+.item1, .item2 {
+    cursor: pointer;
+}
+.imgzong .item2 .el-image{
+    margin: 0 0.099rem;
+    width: .3125rem;
+    vertical-align: middle;
+    padding: .0469rem;
+}
+.imgzong .item2 span {
+    display: block;
+    text-align: center;
+}
+
+.imgzong .listitem span {
+    font-size: .0729rem;
+}
+.el-tabs__header{
+    padding: 0;
+    margin: 0;
+}
+.my-header{
+    line-height: 40px;
+    height: 40px;
+    text-align: left;
+}
+.my-header .el-image{
+    width: 28px;
+    margin-top: 6px;
+
+}
+.my-header h4{
+    font-size: 14px;
+    font-weight: 700;
+    color: #fff;
+    text-align: left;
+    font-style: normal;
+    text-transform: none;
+    display: inline-block;
+    padding-left: 5px;
+}
+.el-tabs{
+    --el-tabs-header-height:.2083rem
+}
+.el-dialog__header{
+    padding:0px 20px; 
+    background-color:#2267B1;   
+    margin: 0;
+}
+.el-image {
+    vertical-align: middle;
+}
+.el-dialog__headerbtn{
+    height: 40px !important;
+    top: 3px;
+}
+.el-button+.el-button{
+    background-color:#2267B1; 
+}
+.summary-dlg {
+    pointer-events: none;
+}
+.el-dialog {
+    pointer-events: auto;
+}
+.numberinput .el-input-number{
+    width: 100% !important;
+
+}
+.numberinput .el-input-number .el-input__inner{
+    text-align: left;
+}
+.el-form-item__label{
+    color: #6D6D6D;
+    font-size: .0677rem;
+    line-height: .1563rem;
+letter-spacing: 1px;
+text-align: right;
+font-style: normal;
+text-transform: none;
+}
+.no-border .el-input,.no-border  .el-input__wrapper {
+    border: none;
+    box-shadow: none !important;
+
+  }
+  .no-border .el-input__wrapper {
+    background-color: rgba(255, 255, 255, 0) !important; /* 设置为白色背景 */
+  }
+  .headersele{
+    width: 97px;
+    height: 9px;
+    margin-top: -5px;
+    background-color: #eee;
+  }
+  .headersele .select-trigger{
+    height: 9px;
+    overflow: hidden;
+  }
+
+  .headersele .el-input__inner{
+    display: none;
+  }
+  .headersele .el-input.is-focus .el-input__wrapper{
+    box-shadow:none !important;
+  }
+  .headersele .el-input .el-select__caret.el-icon{
+    top: -11px;
+  }
+  .sel .el-select{
+    width: 100%;
+  }
+  .el-form-item{
+    margin-bottom: 8px;
+  }
+  .border2{
+    border-radius: 10px 10px 10px 10px;
+    border: 1px solid #888888;
+    padding: 10px;
+    position: relative;
+    margin-top: 24px;
+  }
+  .title2{
+    display: inline-block;
+    background-color: #fff;
+    padding: 10px;
+    color: #333;
+    font-weight: 600;
+    position: absolute;
+    top: -20px;
+    left: 20px
+
+  }
+  .threelist{
+    display: flex;
+  }
+  .floatitem .el-image{
+   margin: 0 10px !important;
+  }
+  .heder_tabs .el-tab-pane{
+    border-bottom: 1px solid #7BB0E8;
+  }
+  .opt_moitor{
+    width: 340px;
+  height:calc(100vh - 341px);
+    background: #FFFFFF;
+    box-shadow: 2px 0px 11px 0px rgba(0,0,0,0.12);
+    border-radius: 10px 10px 10px 10px;
+    float: right;
+    padding: 12px;
+    position: absolute;
+    right: 0;
+    top: 0;
+    overflow-y: auto;
+    overflow-x: hidden;
+  }
+  .opt_moitor h3{
+    text-align: left;
+  }
+  .echartitem{
+    width: 100%;
+    height: auto;
+    background: #FFFFFF;
+border-radius: 0px 0px 0px 0px;
+border: 1px solid rgba(0,0,0,0.3);
+position: relative;
+  }
+  .sev{
+    margin-top: 50px;
+  }
+  .magright{
+    margin-right: 40px !important;
+  }
+  .disflex{
+    display: flex;
+  }
+  .sev_ruwu .el-input{
+    width: 100%;
+    height: 31px;
+    padding:0 10px;
+  }
+  .sev_ruwu .el-select{
+    width: 236px;
+  }
+  .sev_ruwu .el-button+.el-button {
+    background-color: #F5FAFF !important;
+    border-radius: 4px 4px 4px 4px;
+  }
+  .btncolor{
+    background-color: #F5FAFF !important;
+    width: 150px !important;
+  }
+  .left_main_content{
+    width: 200px;
+    height: calc(100vh - 184px);
+background: #FFFFFF;
+box-shadow: 2px 0px 11px 0px rgba(0,0,0,0.12);
+border-radius: 10px 10px 10px 10px;
+  }
+  .mianflex{
+    display: flex;
+  }
+  .main_model{
+    width: 100%;
+    height:calc(100vh - .9531rem) ;
+    text-align: center;
+    position: relative;
+  }
+  /* 基础样式 */
+.custom-tree .el-tree-node__label {
+  /* font-weight: bold; */
+  font-size: 15px; /* 基础字体大小 */
+  color: #383838 ;
+  font-family: 'Inter-Regular';
+}
+.treetiele{
+  padding: 6px;
+  font-family: Inter, Inter;
+font-weight: 600;
+font-size: .0833rem;
+color: #1A1A1A;
+line-height: .125rem;
+text-align: left;
+font-style: normal;
+text-transform: none
+}
+.el-tree-node__content{
+  position: relative;
+}
+.custom-tree .el-tree-node__children .el-tree-node__content .treesvgi  i::before{
+  
+content: "";
+display: block;
+width: 1px;
+height: 24px;
+/* background: #000; */
+border-left: 0.5px dashed #383838;
+bottom:0px;
+position: absolute;
+transform: scale(0.5, 1);
+}
+.el-tree .el-tree-node__content{
+  font-size: .0833rem; /* 这里设置为20px,你可以根据需求调整大小 */
+}
+.custom-tree .el-tree-node__children .el-tree-node__content .treesvgi {
+  font-size: .0729rem !important; /* 第二级字体大小 */
+  font-weight: 400;
+  color: #383838 ;
+  font-family: 'Inter-Regular';
+  
+}
+.custom-tree .el-tree-node__children .el-tree-node__children .el-tree-node__label {
+  font-size: .0625rem; /* 第三级字体大小 */
+  color: #1A1A1A ;
+  font-family: 'Inter-Regular';
+}
+.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{
+  background-color: rgba(0,0,0,0);
+  color: #0077F0 !important;
+  font-family: 'Inter-Regular';
+}
+.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content .el-tree-node__label {
+  background-color: rgba(0,0,0,0);
+  color: #0077F0 !important;
+}
+.el-tabs__item{
+position:relative;
+}
+.el-tabs--card>.el-tabs__header .el-tabs__item.is-active::before{
+  content: "";
+  display: block;
+  width: 45%;
+  height: 2px;
+  background: linear-gradient( 270deg, #1E69FF 0%, #5B91FF 100%);
+  border-radius: 0px 0px 0px 0px;
+  bottom: 3px;
+  position: absolute;
+}
+
+.el-icon-folder{
+
+  background: url(../assets/img/jia.png)no-repeat 0;
+  content: "";
+  display: block;
+  width: 16px;
+  height: 16px;
+  font-size: 16px;
+  background-size: 16px;
+}
+.el-icon-collection-tag{
+  background: url(../assets/img/jian.png)no-repeat 0;
+  content: "";
+  display: block;
+  width: 16px;
+  height: 16px;
+  font-size: 16px;
+  background-size: 16px;
+}
+.treesvgi{
+  display: contents;
+}
+.herader_tabs{
+  text-align: center;
+  font-family: Microsoft YaHei, Microsoft YaHei;
+font-weight: 400;
+font-size: 14px;
+color: #1A1A1A;
+line-height: 27px;
+letter-spacing: 1px;
+text-align: center;
+font-style: normal;
+margin-top: -6px;
+}
+.margr{
+  margin: 0 10px;
+}
+.Role .item2 .el-image{
+  padding: .0365rem .0469rem .0365rem  .0469rem !important;
+
+}
+.femFooter {
+  position: absolute;
+  /* position: fixed; */
+  width: 100%;
+  bottom: 0px;
+}
+.el-footer{
+ --el-footer-padding: 0 0 0 20px;
+    --el-footer-height: auto;
+}
+.left_main{
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+.footerText .el-textarea__inner{
+  width: 100%;
+  height: 130px!important;
+  border: 0;
+  font-size: 12px;
+  color: #333;
+  padding: 2px 20px;
+  padding-bottom: 20px;
+}
+.main_model{
+  width: 100%;
+  /* height: 80vh; */
+  display: flex;
+  flex-direction: column;
+
+}
+.main_container{
+  width: 100%;
+}
+.maxh221{
+ height: calc(100vh - 1.8802rem);
+  flex: 1;
+}
+/* .main_container{
+  display: flex;
+} */
+.pading_foter{
+      box-shadow: 0 0 0 1px #dcdfe6 inset;
+      padding: 1px;
+      overflow: hidden;
+      border-radius: 5px;
+}
+button:focus, button:focus-visible{
+  outline:none;
+}
+
+/* Webkit内核浏览器(Chrome、Safari等)*/
+::-webkit-scrollbar {
+    width: 4px;
+    /* 设置滚动条宽度 */
+    background-color: #dcdfe6;
+    /* 设置滚动条背景颜色 */
+  }
+  
+  /* 滑块样式 */
+  ::-webkit-scrollbar-thumb {
+    border-radius: 2px;
+    /* 设置滑块边角半径 */
+    background-color:#eee ;
+    /* 设置滑块背景颜色 */
+  }
+  
+  /* 滑块在hover状态时的样式 */
+  ::-webkit-scrollbar-thumb:hover {
+    background-color: #dcdfe6;
+    /* 设置滑块在hover状态下的背景颜色 */
+  }
+  
+  /* 滚动条轨道样式 */
+  ::-webkit-scrollbar-track {
+    background-color: #dcdfe6;
+    /* 设置滚动条轨道背景颜色 */
+  }
+  .el-input__inner{
+    --el-input-inner-height: calc(var(--el-input-height, .1667rem) - .0104rem) !important;
+  }
+  .left_main  .el-tabs__item {
+    color: #1A1A1A;
+  }
+  .panetab .el-image {
+ 
+    width: 60px;
+    vertical-align: middle;
+    padding: 10px;
+}
+.ve_menu_logo{
+  text-align: left;
+}
+.lefttext .el-form-item__label{
+  text-align: left !important;
+  justify-content: flex-start !important;
+}
+.el-dialog__body{
+  max-height: 630px;
+  overflow-y: auto;
+}

+ 204 - 39
src/views/index.vue

@@ -534,7 +534,7 @@
             <div class="numberinput">
               <el-form>
                 <el-form-item label="代理模型类型:" :label-width="formLabelWidth2">
-                  <el-select   v-model="canshu" :suffix-icon="CaretBottom" placeholder="请选择">
+                  <el-select   v-model="agval" :suffix-icon="CaretBottom" placeholder="请选择">
                           <el-option
                             v-for="item in agelist"
                             :key="item.value"
@@ -544,7 +544,7 @@
                         </el-select>
                 </el-form-item>  
                 <el-form-item label="设计空间类型:" :label-width="formLabelWidth2">
-                  <el-select   v-model="canshu" :suffix-icon="CaretBottom" placeholder="请选择">
+                  <el-select   v-model="agval1" :suffix-icon="CaretBottom" placeholder="请选择">
                           <el-option
                             v-for="item in agelist1"
                             :key="item.value"
@@ -554,7 +554,7 @@
                         </el-select>
                 </el-form-item> 
                 <el-form-item label="试验设计方法:" :label-width="formLabelWidth2">
-                  <el-select   v-model="canshu" :suffix-icon="CaretBottom" placeholder="请选择">
+                  <el-select   v-model="agval2" :suffix-icon="CaretBottom" placeholder="请选择">
                           <el-option
                             v-for="item in agelist2"
                             :key="item.value"
@@ -885,11 +885,180 @@
               </div>
             </template>
           </el-dialog>
+          <!-- 优化器 -->
+               <el-dialog v-model="dialog.optimizer"
+           align-center :modal="false" :close-on-click-modal="true"
+            :append-to-body="true" draggable :fullscreen="false" :modal-append-to-body="false" modal-class="summary-dlg"
+            :before-close="handleClose" width="430" class="dialog_class bgcolor tianjia sel">
+
+            <template #header="{ titleId, titleClass }">
+              <div class="my-header ">
+                <el-image :src="getImgPath('t2.png')" fit="contain"></el-image>
+                <h4 :id="titleId" :class="titleClass">优化器</h4>
+              </div>
+            </template>
+            <div class="numberinput lefttext">
+              <el-form >
+                <span>代理模型</span>
+                <el-form-item label="代理模型类型:" :label-width="formLabelWidth2">
+                  <el-select   v-model="agval" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in agelist"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>  
+                <el-form-item label="设计空间类型:" :label-width="formLabelWidth2">
+                  <el-select   v-model="agval1" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in agelist1"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item> 
+                <el-form-item label="试验设计方法:" :label-width="formLabelWidth2">
+                  <el-select   v-model="agval2" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in agelist2"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item> 
+                <el-form-item label="初始样本点数:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <span>加点方法</span>
+                <el-form-item label="最大样本点数:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="加点准则:" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                <el-form-item label="单次迭代新增样本点数:" :label-width="formLabelWidth1">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="约束处理方法:" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval1" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist1"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                <el-form-item label="优化算法" :label-width="formLabelWidth2">
+                  <el-select   v-model="ys" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in yslist"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                     <el-form-item label="种群规模:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="最大进化代数:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="交叉概率:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="变异概率:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="交叉算子:" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval2" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist2"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                <el-form-item label="竞赛规模:" :label-width="formLabelWidth2">
+                  <el-input-number v-model="num" :min="1" :max="10" controls-position="right" />
+                </el-form-item>
+                <el-form-item label="保留优选策略:" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval3" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist3"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                <el-form-item label="变异算子选择:" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval4" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist4"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                <el-form-item label="precision:" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval7" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist7"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+                <el-form-item label="GPU" :label-width="formLabelWidth2">
+                  <el-select   v-model="addval8" :suffix-icon="CaretBottom" placeholder="请选择">
+                          <el-option
+                            v-for="item in addlist8"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                </el-form-item>
+              </el-form>
+            </div>
+            <template #footer>
+              <div class="dialog-footer">
+                <el-button @click="dialog.optimizer = false">取消</el-button>
+                <el-button type="primary" @click="dialog.optimizer = false">
+                  确定
+                </el-button>
+              </div>
+            </template>
+          </el-dialog>
           <!-- 内容区 -->
           <div class="main  mianflex">
             <!--left菜单栏  -->
             <div class="left_main">
-            <div class="left_main_content">
+              <div class="left_main_content">
+              <el-tabs
+              v-model="tabName"
+              type="card"
+              class="demo-tabs"
+              @tab-click="handleClick"
+            >
+              <el-tab-pane label="优化设计" name="one">
+              
               <p class="treetiele">优化设计</p>
               <el-tree
              class="custom-tree"
@@ -915,16 +1084,25 @@
   
                 </template>
           </el-tree>
-            </div>
-            
+           
+              </el-tab-pane>
+              <el-tab-pane label="组件" name="tow">
+                <!-- <div class="panetab">
+                <el-image :src="getImgPath('f41.png')" fit="cover" />
+                <span style=" display: block;">测试函数模版</span>
+              </div> -->
+              <Sidebar /> 
+              </el-tab-pane>
+            </el-tabs>
+          
+          </div>
             </div>
           <!-- 放图形 -->
           <div class="main_container">
-            <div class="main_model">图形
+            <div class="main_model">
+              <vuefindex :optimizer="dialog.optimizer" @optimizerfalse="optimizerfalse()"></vuefindex>
               <div  class="maxh221">
-            <!-- <h3>mitt.vue</h3> -->
-              <!-- <sixindex/><br>
-              <sixchine/> -->
+           
               <!-- 右侧边栏开始 -->
                   <!-- 优化监控echarts -->
              <div class="opt_moitor" v-if="tabactive=='优化监控'">
@@ -990,16 +1168,21 @@ import { ref, onMounted, reactive, } from "vue";
 import myheader from "@/components/header.vue"
 import { ElMessage, ElButton, ElDialog, ElSelect } from 'element-plus'
 import { Edit,CaretBottom } from '@element-plus/icons-vue'
-import '@/utils/flexible'
+// import '@/utils/flexible'
 import s0 from "@/assets/img/s0.png"
 import optmonitor from './echart/optimize_monitor.vue'
 import sixtop from './echart/six_top.vue'
 import sixbottom from './echart/six_bottom.vue'
-import sixindex from './demo/index.vue'
+import sixindex from './demo/index.vue'      
 import sixchine from './demo/chine.vue'
+import modelb from './vueflow/modelb.vue'
+import vuefindex from './vueflow/index.vue'
+import Sidebar from './vueflow/Sidebar.vue'
+
 let logs=ref("");
 let elodingfalse=ref(false);
 let footerShow=ref(false);
+let tabName=ref("one")
 const treeData = ref([
   // { 
     // id:0,
@@ -1200,6 +1383,9 @@ let agelist = ref([
 { label: '超参数优化方法', value: '超参数优化方法' },
 { label: 'Hooke Jeeves方法循环次数', value: 'Hooke Jeeves方法循环次数' },
 ])
+let agval=ref("Kriging模型")
+let agval1=ref("固定设计空间")
+let agval2=ref("拉丁超立方")
 let agelist1 = ref([
 { label: '固定设计空间', value: '固定设计空间' },
 ])
@@ -1248,6 +1434,7 @@ let dialog = ref({
   constraint:false,
   parameter:false,
   agency:false,
+  optimizer:false,
   enddialog:false,
   addfun:false,
   sufun:false,
@@ -1440,6 +1627,11 @@ const handleNodeClick = (data) => {
    tabactive.value=data.label;
    dialogbolen();
 }
+const optimizerfalse=(val)=>{
+  console.log(11111)
+  dialog.value.optimizer=true;
+  console.log(dialog.value.optimizer);
+}
 
 // 模块选择
 const clickgeometry = (e, index, key,name) => {
@@ -1557,32 +1749,5 @@ const targetclick=()=>{
 }
 //没有子节点
 
-/* Webkit内核浏览器(Chrome、Safari等)*/
-::-webkit-scrollbar {
-  width: 4px;
-  /* 设置滚动条宽度 */
-  background-color: #dcdfe6;
-  /* 设置滚动条背景颜色 */
-}
-
-/* 滑块样式 */
-::-webkit-scrollbar-thumb {
-  border-radius: 2px;
-  /* 设置滑块边角半径 */
-  background-color:#eee ;
-  /* 设置滑块背景颜色 */
-}
-
-/* 滑块在hover状态时的样式 */
-::-webkit-scrollbar-thumb:hover {
-  background-color: #dcdfe6;
-  /* 设置滑块在hover状态下的背景颜色 */
-}
-
-/* 滚动条轨道样式 */
-::-webkit-scrollbar-track {
-  background-color: #dcdfe6;
-  /* 设置滚动条轨道背景颜色 */
-}
 
 </style>

+ 16 - 0
src/views/vueflow/DropzoneBackground.vue

@@ -0,0 +1,16 @@
+<script  setup>
+import { Background } from '@vue-flow/background'
+
+</script>
+
+<template>
+  <div class="dropzone-background">
+    <Background :size="2" :gap="20" pattern-color="#BDBDBD" />
+    <!-- <moban/> -->
+    <!-- <div class="overlay">
+
+       <slot /> 
+    </div> -->
+
+  </div>
+</template>

+ 59 - 0
src/views/vueflow/Sidebar.vue

@@ -0,0 +1,59 @@
+<script setup>
+import useDragAndDrop from './useDnD'
+import f41 from '@/assets/img/f41.png'
+import f11 from '@/assets/img/f11.png'
+import f32 from '@/assets/img/f32.png'
+import f33 from '@/assets/img/f33.png'
+import f12 from '@/assets/img/f12.png'
+import f21 from '@/assets/img/f21.png'
+import f22 from '@/assets/img/f22.png'
+const { onDragStart,onDragLeave,} = useDragAndDrop()
+</script>
+
+<template>
+  <aside>
+<!-- 
+    <div class="nodes">
+      <div class="vue-flow__node-input" :draggable="true" @dragstart="onDragStart($event, 'input')">Input Node</div>
+
+      <div class="vue-flow__node-default" :draggable="true" @dragstart="onDragStart($event, 'default')">Default Node</div>
+
+      <div class="vue-flow__node-output" :draggable="true" @dragstart="onDragStart($event, 'output')">Output Node</div>
+   
+      <div class="vue-flow__node-output" :draggable="false" >
+        <el-image :src="f41" fit="cover" />
+      </div>
+    </div> -->
+    <div  class="nodes moban">
+    <button class="stop-btn" title="stop" @click="stop" :draggable="true"   @dragstart="onDragStart($event, 'default','1')">
+      <el-image :src="f11" fit="cover" />
+         <span class="spinner">开始</span>
+    </button>
+    <button class="stop-btn" title="stop" @click="stop" :draggable="true"   @dragstart="onDragStart($event, 'default','2')">
+      <el-image :src="f12" fit="cover" />
+         <span class="spinner">结束</span>
+    </button>
+    <button class="stop-btn" title="stop" @click="stop" :draggable="true"   @dragstart="onDragStart($event, 'default','3')">
+      <el-image :src="f32" fit="cover" />
+         <span class="spinner">优化器</span>
+    </button>
+    <!-- <div class="vue-flow__node-input" :draggable="true" @dragstart="onDragStart($event, 'input')">Input Node3333</div> -->
+  </div>
+<div class="moban">
+  <button class="stop-btn" title="stop" @click="stop" :draggable="true"   @dragstart="onDragStart($event, 'default','4')">
+      <el-image :src="f41" fit="cover" />
+         <span class="spinner">模版</span>
+    </button>
+</div>
+  </aside>
+</template>
+<style scoped>
+.moban button{
+  margin: 10px;
+}
+.moban .el-image{
+  width: 40px;}
+  .moban span{
+    display: block;
+  }
+</style>

+ 206 - 0
src/views/vueflow/demo.vue

@@ -0,0 +1,206 @@
+<template>
+<div>
+  <VueFlow :nodes="nodes" :edges="edges">
+    <!-- <Panel position="top-left"> -->
+    <template #node-default="props">
+      <Handle type="source" :position="Position.Right" />
+      <div class="custom-node icons"  >
+    <img :src="props.data.image" alt="节点图片" />
+    <span>{{props.data.label }}</span>
+  </div>
+  
+  <!-- <Handle id="source-a" type="source" :position="Position.Right" style="top: 10px" />
+<Handle id="source-b" type="source" :position="Position.Right" style="bottom: 10px; top: auto;" /> -->
+  <!-- <Handle type="source" :position="Position.Left" />
+  <Handle type="target" :position="Position.Top" />
+  <Handle type="target" :position="Position.Bottom" /> -->
+    </template>
+  <Background  :gap="5" :size="0.5" :patternColor="'#C60707 '" />
+  <Controls />
+  <!-- </Panel> -->
+</VueFlow>
+</div>
+</template>
+<script setup>
+import { ref, onMounted } from 'vue'
+import { VueFlow,Handle, Position } from '@vue-flow/core'
+import { Background } from '@vue-flow/background'
+import { MiniMap } from '@vue-flow/minimap'
+import { ControlButton, Controls } from '@vue-flow/controls'
+import f11 from '@/assets/img/f11.png'
+import f32 from '@/assets/img/f32.png'
+import f33 from '@/assets/img/f33.png'
+import f12 from '@/assets/img/f12.png'
+import f21 from '@/assets/img/f21.png'
+import f22 from '@/assets/img/f22.png'
+const isSource = true;
+const connectionPosition = Position.Top;
+ 
+const handleSource = {
+  type: 'source',
+  position: connectionPosition,
+  // 其他可选配置...
+};
+ 
+const handleTarget = {
+  type: 'target',
+  position: Position.Bottom, // 目标句柄在底部
+  // 其他可选配置...
+};
+const nodes = ref([
+  {
+data:{label: '开始', image: '/src/assets/img/f11.png'},
+id: "node_0",
+position: {x:245, y: 317},
+type: "default",
+handles: [
+            {
+              id: 'handle1',
+              type: 'default',
+              position: 'right',
+            },
+          ],
+},
+{
+data:{label: '优化器', image: '/src/assets/img/f32.png'},
+id: "node_1",
+position: {x: 435, y: 317},
+type: "default",
+handles: [
+            {
+              id: 'handle2',
+              type: 'default',
+              position: 'left',
+            },
+          ],
+},
+{
+data:{label: 'Rosenbank', image: '/src/assets/img/f33.png'},
+id: "node_2",
+position: {x: 630, y: 317},
+// type: "default",
+},
+{
+data:{label: '结束', image: '/src/assets/img/f12.png'},
+id: "node_3",
+position: {x: 804, y: 317},
+type: "default",
+},
+{
+data:{label: '输入1', image: '/src/assets/img/f21.png'},
+id: "node_4",
+position: {x: 521, y: 146},
+type: "default",
+draggable: true, 
+handle: [
+            {
+              id: 'handle_4',
+              position: 'Bottom',
+            },
+          ],
+},
+{
+data:{label: '输入2', image: '/src/assets/img/f21.png'},
+id: "node_5",
+position: {x:712, y: 146},
+type: "default",
+sourceHandle: 'Bottom'
+},
+{
+data:{label: '输出', image: '/src/assets/img/f22.png'},
+id: "node_6",
+position: {x: 641, y: 519},
+type: "default",
+sourceHandle: 'Top'
+},
+
+]);
+let connections=ref([
+        {
+          source: 'handle1', // 源句柄ID
+          target: 'handle2', // 目标句柄ID
+        },
+      ])
+const edges = ref([
+{
+  id: 'e1->2',
+  source: 'node_0',
+  target: 'node_1',
+  type: 'straight',
+},
+{
+  id: 'e2->3',
+  source: 'node_1',
+  target: 'node_2',
+  type: 'straight'
+},
+{
+  id: 'e3->4',
+  source: 'node_2',
+  target: 'node_3',
+  type: 'straight' 
+},
+{
+  id: 'e4->5',
+  source: 'node_2',
+  target: 'node_4',
+  type: 'straight' 
+},
+{
+  id: 'e5->6',
+  source: 'node_2',
+  target: 'node_5',
+  type: 'straight' 
+
+},
+{
+  id: 'e6->7',
+  source: 'node_2',
+  target: 'node_6',
+  type: 'straight' 
+},
+]);
+</script>
+<style>
+
+</style>
+<style lang="scss" scoped>
+//  @import '@vue-flow/minimap/dist/style.css';
+@import '@vue-flow/minimap/dist/style.css';
+@import './main.css';
+
+.vue-flow{
+width: 100%;
+  height: 100vh;
+  margin: 0 auto;
+  border: 1px solid;
+  overflow: auto;
+}
+.vue-flow__node-custom {
+  background: purple;
+  color: white;
+  border: 1px solid purple;
+  border-radius: 4px;
+  box-shadow: 0 0 0 1px purple;
+  padding: 8px;
+}
+
+.icons img{
+  width: 30px;    
+
+}
+.icons span{
+  display: block;
+  font-size: 13px;
+}
+</style>
+<style>
+.vue-flow__node.draggable {
+  width: 64px !important;
+    height: 64px !important;
+}
+.vue-flow__node {
+          stroke: none; /* 移除节点边框 */
+        }
+</style>
+

+ 62 - 0
src/views/vueflow/index.vue

@@ -0,0 +1,62 @@
+<template>
+  <div class="dnd-flow" >
+    <VueFlow :nodes="nodes" :edges="edges"  @drop="onDrop"   @node-drop="handleNodeDrop"   @dragover="onDragOver" @dragleave="onDragLeave"    @node-click="onNodeClick">
+      <template #node-default="props">
+      <modelb :node="props" />
+    </template>
+      <!-- <DropzoneBackground
+        :style="{
+          backgroundColor: isDragOver ? '#e7f3ff' : 'transparent',
+          transition: 'background-color 0.2s ease',
+        }"
+      >
+      </DropzoneBackground> -->
+    <!-- </Panel> -->
+    </VueFlow>
+
+    <!-- <Sidebar /> -->
+  <!-- 优化器 -->
+  
+  </div>
+</template>
+
+
+<script setup>
+import { ref } from 'vue'
+import { VueFlow, useVueFlow,Position } from '@vue-flow/core'
+import DropzoneBackground from './DropzoneBackground.vue'
+import useDragAndDrop from './useDnD'
+import f11 from '@/assets/img/f11.png'
+ import "./main.css";//重置样式
+ import modelb from './modelb.vue'
+// import func from 'vue-temp/vue-editor-bridge'
+// import {initialNodes,initialEdges } from './node'
+// const nodes = ref(initialNodes)
+let emit = defineEmits(['optimizerfalse']);
+const props = defineProps({
+  // optimizer: {
+  //   type: Boolean,
+  //   required: true,
+  // },
+})
+// const edges = ref(initialEdges)
+const { onConnect, addEdges } = useVueFlow()
+let node=ref([]);
+const { onDragOver, onDrop, onDragLeave, isDragOver} = useDragAndDrop()
+function handleNodeDrop(e){
+  console.log(11111)
+  console.log(e);
+}
+const edges = ref([]);
+const nodes = ref([]);
+onConnect(addEdges)
+function onNodeClick(e){
+  console.log(e.node.data.label);
+  if(e.node.data.label=='优化器'){
+    console.log(e.node);
+    emit('optimizerfalse', true);
+  }
+
+}
+</script>
+

+ 101 - 0
src/views/vueflow/main.css

@@ -0,0 +1,101 @@
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/core@1.39.0/dist/style.css';
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/core@1.39.0/dist/theme-default.css';
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/controls@latest/dist/style.css';
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/minimap@latest/dist/style.css';
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/node-resizer@latest/dist/style.css';
+
+html,
+body,
+#app {
+  margin: 0;
+  height: 100%;
+}
+
+#app {
+  text-transform: uppercase;
+  font-family: 'JetBrains Mono', monospace;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-align: center;
+  color: #2c3e50;
+}
+
+.vue-flow__minimap {
+  transform: scale(75%);
+  transform-origin: bottom right;
+}
+
+.dnd-flow {
+    flex-direction:column;
+    display:flex;
+    height:100%
+}
+
+.dnd-flow aside {
+    color:#fff;
+    font-weight:700;
+    border-right:1px solid #eee;
+    padding:15px 10px;
+    font-size:12px;
+    background:#10b981bf;
+    -webkit-box-shadow:0px 5px 10px 0px rgba(0,0,0,.3);
+    box-shadow:0 5px 10px #0000004d
+}
+
+.dnd-flow aside .nodes>* {
+    margin-bottom:10px;
+    cursor:grab;
+    font-weight:500;
+    -webkit-box-shadow:5px 5px 10px 2px rgba(0,0,0,.25);
+    box-shadow:5px 5px 10px 2px #00000040
+}
+
+.dnd-flow aside .description {
+    margin-bottom:10px
+}
+
+.dnd-flow .vue-flow-wrapper {
+    flex-grow:1;
+    height:100%
+}
+
+@media screen and (min-width: 640px) {
+    .dnd-flow {
+    flex-direction:row
+}
+
+.dnd-flow aside {
+    min-width:25%
+}
+
+
+}
+
+@media screen and (max-width: 639px) {
+    .dnd-flow aside .nodes {
+    display:flex;
+    flex-direction:row;
+    gap:5px
+}
+
+
+}
+
+.dropzone-background {
+    position:relative;
+    height:100%;
+    width:100%
+}
+
+.dropzone-background .overlay {
+    position:absolute;
+    top:0;
+    left:0;
+    height:100%;
+    width:100%;
+    display:flex;
+    align-items:center;
+    justify-content:center;
+    z-index:1;
+    pointer-events:none
+}

+ 77 - 0
src/views/vueflow/modelb.vue

@@ -0,0 +1,77 @@
+<script  setup>
+import { ref, onMounted, reactive, } from "vue";
+// import {initialNodes,initialEdges } from './node'
+// const nodes = ref(initialNodes)
+// const edges = ref(initialEdges)
+import f11 from '@/assets/img/f11.png'
+import f32 from '@/assets/img/f32.png'
+import f33 from '@/assets/img/f33.png'
+import f12 from '@/assets/img/f12.png'
+import f21 from '@/assets/img/f21.png'
+import f22 from '@/assets/img/f22.png'
+const props = defineProps({
+  node: {
+    type: Object,
+    required: true,
+  },
+  sourcePosition: {
+    type: String,
+  },
+  targetPosition: {
+    type: String,
+  },
+})
+
+onMounted(() => {
+});
+</script>
+<template>
+  <div>
+    <!-- v-for="(node,index) in props.data" :key="index" -->
+    <div class="custom-node icons" :id="`node-${node.id}`" >
+    <img :src="props.node.data.image" alt="节点图片" />
+    <span>{{props.node.data.label }}</span>
+  </div>
+
+  </div>
+  
+</template>
+<style scoped>
+
+.icons img{
+  width: 30px;
+
+}
+.icons span{
+  display: block;
+  font-size: 13px;
+}
+</style>
+<style>
+.vue-flow__node.draggable {
+  width: 64px !important;
+    height: 64px !important;
+    border: none;
+}
+.vue-flow__node {
+          stroke: none; /* 移除节点边框 */
+        }
+        
+.vue-flow__edge-path {
+  fill: none;
+  stroke-width: 1;
+  marker-end: url(#vue-flow__arrow);
+}
+ 
+.vue-flow__edge-text {
+  display: none;
+}
+.vue-flow__node-custom {
+    background: purple;
+    color: white;
+    border: 1px solid purple;
+    border-radius: 4px;
+    box-shadow: 0 0 0 1px purple;
+    padding: 8px;
+}
+</style>

+ 79 - 0
src/views/vueflow/node.js

@@ -0,0 +1,79 @@
+import { MarkerType } from '@vue-flow/core'
+import f11 from '@/assets/img/f11.png'
+import f32 from '@/assets/img/f32.png'
+import f33 from '@/assets/img/f33.png'
+import f12 from '@/assets/img/f12.png'
+import f21 from '@/assets/img/f21.png'
+import f22 from '@/assets/img/f22.png'
+export const initialNodes = [
+  {
+    id: '1',
+    data: { label: '开始' },
+    position: { x: 250, y: 0 },
+    class: 'light',
+    type: 'custom',
+    image: f11,
+    label: '开始',
+    marker: 'custom',
+    // 其他自定义数据
+  },
+  {
+    id: '2',
+    type: 'custom',
+    image: f32,
+    label: '结束',
+    position: { x: 300, y: 100 },
+    class: 'light',
+  },
+  {
+    id: '3',
+    data: { label: 'Node 3' },
+    position: { x: 400, y: 100 },
+    class: 'light',
+  },
+  {
+    id: '4',
+    data: { label: '结束' },
+    position: { x: 150, y: 200 },
+    class: 'light',
+  },
+  {
+    id: '5',
+    type: 'output',
+    data: { label: 'Node 5' },
+    position: { x: 300, y: 300 },
+    class: 'light',
+  },
+]
+
+export const initialEdges = [
+  {
+    id: 'e1-2',
+    source: '1',
+    target: '2',
+    animated: true,
+  },
+  {
+    id: 'e1-3',
+    source: '1',
+    target: '3',
+    label: 'edge with arrowhead',
+    markerEnd: MarkerType.ArrowClosed,
+  },
+  {
+    id: 'e4-5',
+    type: 'step',
+    source: '4',
+    target: '5',
+    label: 'Node 2',
+    style: { stroke: 'orange' },
+    labelBgStyle: { fill: 'orange' },
+  },
+  {
+    id: 'e3-4',
+    type: 'smoothstep',
+    source: '3',
+    target: '4',
+    label: 'smoothstep-edge',
+  },
+]

+ 272 - 0
src/views/vueflow/useDnD.js

@@ -0,0 +1,272 @@
+import { useVueFlow } from '@vue-flow/core'
+import { ref, watch } from 'vue'
+import f11 from '@/assets/img/f11.png'
+import f32 from '@/assets/img/f32.png'
+import f33 from '@/assets/img/f33.png'
+import f12 from '@/assets/img/f12.png'
+import f21 from '@/assets/img/f21.png'
+import f22 from '@/assets/img/f22.png'
+import f41 from '@/assets/img/f41.png'
+import { E } from '@kitware/vtk.js/macros2'
+import { Right } from '@element-plus/icons'
+import { LEFT_CHECK_CHANGE_EVENT } from 'element-plus'
+let nid = 0;
+let id=0
+let datas={}
+
+/**
+ * @returns {string} - A unique id.
+ */
+function getId() {
+  return `node_${id++}`
+}
+function imagefun(){
+  // console.log(id);
+  if(nid==1){
+    return  datas = {label: '开始', image:f11}
+    }else if(nid==2){
+      return datas = {label:'结束', image:f12}
+    }else if(nid==3){
+      return datas = {label:'优化器', image:f32}
+    }else{
+      return datas = {label:'模版', image:f41}
+    }
+
+  }
+
+/**
+ * In a real world scenario you'd want to avoid creating refs in a global scope like this as they might not be cleaned up properly.
+ * @type {{draggedType: Ref<string|null>, isDragOver: Ref<boolean>, isDragging: Ref<boolean>}}
+ */
+const state = {
+  /**
+   * The type of the node being dragged.
+   */
+  draggedType: ref(null),
+  isDragOver: ref(false),
+  isDragging: ref(false),
+}
+
+export default function useDragAndDrop() {
+  const { draggedType, isDragOver, isDragging } = state
+
+  const { addNodes, addEdges,screenToFlowCoordinate, onNodesInitialized, updateNode } = useVueFlow()
+
+  watch(isDragging, (dragging) => {
+    document.body.style.userSelect = dragging ? 'none' : ''
+  })
+
+  function onDragStart(event, type,id) {
+ 
+    nid=id;
+    if (event.dataTransfer) {
+      event.dataTransfer.setData('application/vueflow', type)
+      event.dataTransfer.effectAllowed = 'move'
+    }
+
+    draggedType.value = type
+    isDragging.value = true
+
+    document.addEventListener('drop', onDragEnd)
+  }
+
+  /**
+   * Handles the drag over event.
+   *
+   * @param {DragEvent} event
+   */
+  function onDragOver(event) {
+    event.preventDefault()
+
+    if (draggedType.value) {
+      isDragOver.value = true
+
+      if (event.dataTransfer) {
+        event.dataTransfer.dropEffect = 'move'
+      }
+    }
+  }
+  function handleNodeDrop(e){
+  
+  }
+  function onDragLeave(e) {
+  
+    isDragOver.value = false
+  }
+
+  function onDragEnd() {
+    isDragging.value = false
+    isDragOver.value = false
+    draggedType.value = null
+    document.removeEventListener('drop', onDragEnd)
+  }
+
+  /**
+   * Handles the drop event.
+   *
+   * @param {DragEvent} event
+   */
+  function onDrop(event) {
+    const position = screenToFlowCoordinate({
+      x: event.clientX,
+      y: event.clientY,
+    })
+
+    const nodeId = getId()
+    const image1=imagefun();
+ 
+    let snodes=ref([]);
+    let sedges=[]
+    if(nid=='4'){
+      const nodes = ref([
+        {
+      data:{label: '开始', image: '/src/assets/img/f11.png'},
+      id: "node_01",
+      position: {x:245, y: 317},
+      type: "default",
+      handle: {
+        type: 'custom',
+        position: 'Right',
+        // 其他自定义句柄属性
+      },
+      },
+      {
+      data:{label: '优化器', image: '/src/assets/img/f32.png'},
+      id: "node_02",
+      position: {x: 435, y: 317},
+      type: "default",
+      inputs: 1, outputs: 1,
+      handle: {
+        type: 'custom',
+        position: 'Left',
+        // 其他自定义句柄属性
+      },
+      },
+      {
+      data:{label: 'Rosenbank', image: '/src/assets/img/f33.png'},
+      id: "node_03",
+      position: {x: 630, y: 317},
+      // type: "default",
+      },
+      {
+      data:{label: '结束', image: '/src/assets/img/f12.png'},
+      id: "node_04",
+      position: {x: 804, y: 317},
+      type: "default",
+      },
+      {
+      data:{label: '输入1', image: '/src/assets/img/f21.png'},
+      id: "node_05",
+      position: {x: 521, y: 146},
+      type: "default",
+      draggable: true, 
+      },
+      {
+      data:{label: '输入2', image: '/src/assets/img/f21.png'},
+      id: "node_06",
+      position: {x:712, y: 146},
+      type: "default",
+      sourceHandle: 'Bottom'
+      },
+      {
+      data:{label: '输出', image: '/src/assets/img/f22.png'},
+      id: "node_07",
+      position: {x: 641, y: 519},
+      type: "default",
+      sourceHandle: 'Top'
+      },
+      
+      ]);
+      let connections=ref([
+              {
+                source: 'handle1', // 源句柄ID
+                target: 'handle2', // 目标句柄ID
+              },
+            ])
+      const edges = ref([
+      {
+        id: 'e1->2',
+        source: 'node_01',
+        target: 'node_02',
+        type: 'straight',
+        sourceHandleId: 'Right',
+        targetHandleId: 'Left',
+        sourceHandleId: 'handleIdOfNode1',
+        targetHandleId: 'handleIdOfNode2',
+      },
+      {
+        id: 'e2->3',
+        source: 'node_02',
+        target: 'node_03',
+        type: 'straight'
+      },
+      {
+        id: 'e3->4',
+        source: 'node_03',
+        target: 'node_04',
+        type: 'straight' 
+      },
+      {
+        id: 'e4->5',
+        source: 'node_03',
+        target: 'node_05',
+        type: 'straight' 
+      },
+      {
+        id: 'e5->6',
+        source: 'node_03',
+        target: 'node_06',
+        type: 'straight' 
+      
+      },
+      {
+        id: 'e6->7',
+        source: 'node_03',
+        target: 'node_07',
+        type: 'straight' 
+      },
+      ]);
+snodes=nodes
+ sedges=edges
+    }else{
+      snodes.value=[];
+      const newNode = {
+        id: nodeId,
+        type: draggedType.value,
+        position,
+        data: image1,
+     
+      }
+      snodes.value.push(newNode)
+      //sedges=edges
+    }
+  
+   // console.log(newNode);
+    /**
+     * Align node position after drop, so it's centered to the mouse
+     *
+     * We can hook into events even in a callback, and we can remove the event listener after it's been called.
+     */
+    const { off } = onNodesInitialized(() => {
+      updateNode(nodeId, (node) => ({
+        position: { x: node.position.x - node.dimensions.width / 2, y: node.position.y - node.dimensions.height / 2 },
+      }))
+
+      off()
+    })
+console.log(snodes.value);
+    addNodes(snodes.value)
+    addEdges(sedges.value)
+  }
+
+  return {
+    draggedType,
+    isDragOver,
+    isDragging,
+    onDragStart,
+    onDragLeave,
+    onDragOver,
+    onDrop,
+    handleNodeDrop,
+  }
+}