liuqiao 1 year ago
parent
commit
76fbd0f3e8
43 changed files with 1590 additions and 206 deletions
  1. BIN
      src/assets/flowimg/gc1.png
  2. BIN
      src/assets/flowimg/gc2.png
  3. BIN
      src/assets/flowimg/gc3.png
  4. BIN
      src/assets/flowimg/wen.png
  5. BIN
      src/assets/flowimg/xuek1.png
  6. BIN
      src/assets/flowimg/xuek2.png
  7. BIN
      src/assets/flowimg/xuek3.png
  8. BIN
      src/assets/flowimg/xuek4.png
  9. BIN
      src/assets/flowimg/xuek5.png
  10. BIN
      src/assets/flowimg/xuek6.png
  11. BIN
      src/assets/flowimg/xuek7.png
  12. BIN
      src/assets/flowimg/xuek8.png
  13. BIN
      src/assets/flowimg/xuek9.png
  14. BIN
      src/assets/img/gc1.png
  15. BIN
      src/assets/img/gc2.png
  16. BIN
      src/assets/img/gc3.png
  17. BIN
      src/assets/img/wen.png
  18. BIN
      src/assets/img/xuek1.png
  19. BIN
      src/assets/img/xuek2.png
  20. BIN
      src/assets/img/xuek3.png
  21. BIN
      src/assets/img/xuek4.png
  22. BIN
      src/assets/img/xuek5.png
  23. BIN
      src/assets/img/xuek6.png
  24. BIN
      src/assets/img/xuek7.png
  25. BIN
      src/assets/img/xuek8.png
  26. BIN
      src/assets/img/xuek9.png
  27. BIN
      src/assets/img/youh1.png
  28. BIN
      src/assets/img/youh2.png
  29. BIN
      src/assets/img/youh3.png
  30. 23 7
      src/style/index.css
  31. 7 0
      src/style/style.css
  32. 366 197
      src/views/home.vue
  33. 1 0
      src/views/vueflow/Sidebar.vue
  34. 1 2
      src/views/vueflow/useDnD.js
  35. 16 0
      src/views/vuetree/DropzoneBackground.vue
  36. 38 0
      src/views/vuetree/Icon.vue
  37. 180 0
      src/views/vuetree/Sidebar.vue
  38. 72 0
      src/views/vuetree/eltree.vue
  39. 226 0
      src/views/vuetree/index.vue
  40. 69 0
      src/views/vuetree/initial-elements.js
  41. 79 0
      src/views/vuetree/main.css
  42. 157 0
      src/views/vuetree/nodes.vue
  43. 355 0
      src/views/vuetree/useDnD.js

BIN
src/assets/flowimg/gc1.png


BIN
src/assets/flowimg/gc2.png


BIN
src/assets/flowimg/gc3.png


BIN
src/assets/flowimg/wen.png


BIN
src/assets/flowimg/xuek1.png


BIN
src/assets/flowimg/xuek2.png


BIN
src/assets/flowimg/xuek3.png


BIN
src/assets/flowimg/xuek4.png


BIN
src/assets/flowimg/xuek5.png


BIN
src/assets/flowimg/xuek6.png


BIN
src/assets/flowimg/xuek7.png


BIN
src/assets/flowimg/xuek8.png


BIN
src/assets/flowimg/xuek9.png


BIN
src/assets/img/gc1.png


BIN
src/assets/img/gc2.png


BIN
src/assets/img/gc3.png


BIN
src/assets/img/wen.png


BIN
src/assets/img/xuek1.png


BIN
src/assets/img/xuek2.png


BIN
src/assets/img/xuek3.png


BIN
src/assets/img/xuek4.png


BIN
src/assets/img/xuek5.png


BIN
src/assets/img/xuek6.png


BIN
src/assets/img/xuek7.png


BIN
src/assets/img/xuek8.png


BIN
src/assets/img/xuek9.png


BIN
src/assets/img/youh1.png


BIN
src/assets/img/youh2.png


BIN
src/assets/img/youh3.png


+ 23 - 7
src/style/index.css

@@ -302,11 +302,11 @@ position: relative;
     width: 150px !important;
   }
   .left_main_content{
-    width: 200px;
+    width: 195px;
     height: calc(100vh - 184px);
 background: #FFFFFF;
 box-shadow: 2px 0px 11px 0px rgba(0,0,0,0.12);
-border-radius: 10px 10px 10px 10px;
+border: 1px solid #2267B1;
   }
   .mianflex{
     display: flex;
@@ -439,10 +439,6 @@ margin-top: -6px;
  --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;
@@ -528,4 +524,24 @@ text-align: left;
 .el-dialog__body{
   max-height: 730px;
   overflow-y: auto;
-}
+}
+.custom-tree{
+  width: 195px;
+height: 180px;
+background: #FFFFFF;
+border-radius: 0px 0px 0px 0px;
+border: 1px solid #2267B1;
+box-sizing: border-box;
+}
+.el-tree-node__content>.el-tree-node__expand-icon{
+  padding: 6px;
+  box-sizing: content-box;
+  font-size: 16px;
+  color: #000000;
+}
+.el-tree-node{
+  padding: 2px 0;
+}
+.youhualog{
+  padding: 20px;
+}

+ 7 - 0
src/style/style.css

@@ -542,4 +542,11 @@ button:focus, button:focus-visible{
 .el-dialog__body{
   max-height: 630px;
   overflow-y: auto;
+}
+.custom-tree{
+  width: 190px;
+height: 180px;
+background: #FFFFFF;
+border-radius: 0px 0px 0px 0px;
+border: 1px solid #2267B1;
 }

+ 366 - 197
src/views/home.vue

@@ -880,50 +880,32 @@
             <!-- 内容区 -->
             <div class="main  mianflex">
               <!--left菜单栏  -->
-              <div class="left_main">
-                <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"
-              style="max-width: 300px"
-              :data="treeData"
-              :props="defaultProps"
-              @node-click="handleNodeClick"
-              :highlight-current="true"
-              :default-expanded-keys="defaultExpandedArr"
-               node-key="id"
-            >        
-            <template #default="{ node, data }">   
-                    <span  class="treesvgi">
-                          <i v-if="!data.children" class=""></i>
-              <i v-else-if="node.expanded" class="el-icon-collection-tag"> </i>
-              <i v-else class="el-icon-folder"> </i>
-                          <span  style="margin-left: 10px">{{ node.label}}</span>
-                    </span>
-    
-                  </template>
-            </el-tree> -->
-            <el-tree :data="datatree"   class="custom-tree" :props="defaultProps" @node-click="handleNodeClick" />
-                </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>
-            
+           <Sidebar />
+              <!-- <div class="left_main">
+
+                <div class="left_main_content el-treeicon">
+                  <el-tree :data="datatree"  class="custom-tree" default-expand-all  :props="defaultProps" @node-click="handleNodeClick">
+                    <template #default="{ node, data }">
+                          <div>
+                            <img :src="data.img" class="custom-image" />
+                            <span class="custom-text">
+                              {{ node.label }}
+                            </span>
+                          </div>
+                        </template>
+                  </el-tree>
+                 <el-tree :data="datatree1"  class="custom-tree1" default-expand-all  :props="defaultProps" @node-click="handleNodeClick">
+                    <template #default="{ node, data }">
+                          <div>
+                            <img :src="getImgPath(data.img)" class="custom-image" />
+                            <span class="custom-text">
+                              {{ node.label }} 
+                            </span>
+                          </div>
+                        </template>
+                  </el-tree> 
             </div>
-              </div>
+              </div> -->
             <!-- 放图形 -->
             <div class="main_container">
               <div class="main_model">
@@ -946,9 +928,101 @@
                 class="femFooter"
               
               >
+              <div class="gooterpading">
+               <div class="footerTitle   el-tag--primary">
+                <div >
+                  <span   v-for="(tab, index) in tabs"  :key="index" :class="{ 'active': activeIndex === index }"
+                  @click="activeIndex = index">{{ tab }}</span>
+                </div>
+                <div>
+                  <li
+                    class="exloadbox"
+                    v-show="elodingfalse"
+                  >
+                    <span>正在求解中</span>
+                    <i class="el-icon-loading"></i>
+                  </li>
+                  <li>
+                    <span >清空</span>
+                  </li>
+                  <li>
+                    <span @click="footerShows('foot')">&#9650;&#9660;</span>
+                  </li>
+                </div>
+              </div> 
+              <div class="footerTextBox"   v-if="activeIndex==0">
+                  <el-input
+                    class="footerText"
+                    type="textarea"
+                    id="textarea_id"
+                    v-model="logs"
+                  ></el-input>
+                </div> 
+              <div class="youhualog" v-if="activeIndex==1">
+                <ul>
+                  <li v-for="(tab, index) in listli"  :key="index" :class="{ 'active2': activeIndex2 === index }"
+                  @click="activeIndex2 = index">{{ tab }}</li>
+                </ul>
+                <div  class="footer-content">
+                <div class="eldesign" v-if="activeIndex2==0">
+                  <el-table :data="designtable" border style="width: 100%">
+                  <el-table-column type="index" label="编号"  width="70" />
+                  <el-table-column prop="name" label="变量名称">
+                    <template #default="{ row }">
+                    <el-input v-model="row.name" @change="handleEdit(row)" />
+                  </template>
+                </el-table-column>
+                  <el-table-column prop="date" label="变量类型">
+                    <template #default="{ row }">
+                    <el-input v-model="row.date" @change="handleEdit(row)" />
+                  </template>
+                </el-table-column>
+                  <el-table-column prop="name" label="上限值">
+                    <template #default="{ row }">
+                    <el-input v-model="row.name" @change="handleEdit(row)" />
+                  </template>
+                </el-table-column>
+                  <el-table-column prop="q" label="权重系数">
+                    <template #default="{ row }">
+                    <el-input v-model="row.q" @change="handleEdit(row)" />
+                  </template>
+                </el-table-column>
+                  <el-table-column prop="cai" label="基准值" width="100">
+                  <template #default="{ row }">
+                    <el-input v-model="row.cai" @change="handleEdit(row)" />
+                  </template>
+                </el-table-column>
+                <el-table-column prop="yin" label="下限值">
+                  <template #default="{ row }">
+                    <el-input v-model="row.yin" @change="handleEdit(row)" />
+                  </template>
+                </el-table-column>
+                </el-table>
+                
+                </div>
+                <div class="elconstraint" v-if="activeIndex2==1">约束条件</div>
+                <div class="eloptimize" v-if="activeIndex2==2">优化目标</div>
+              </div>
+              <div class="dibu">
+                <div class="footer-add">
+                  <div class="sev_ruwu">
+                  <div class="disflex "> 
+                  <el-form-item label="新增变量数:">   
+                <el-input v-model="tableval" maxlength="18"
+                    oninput="value=value.replace(/[^\a-\z\A-\Z0-9\u4E00-\u9FA5]/g,'')" class="w-50 m-2"
+                    placeholder="请输入关键字" />   </el-form-item>
+                    <el-button class="btncolor">导入</el-button>
+                    <el-button class="btncolor" @click="onAddItem">新增</el-button>
+                    <el-button class="btncolor">确认</el-button>
+                </div>
+              </div>
+                </div>
+              </div>
+          </div>
               <div class="pading_foter">
+             
                 <!-- 日志 -->
-                <div class="footerTitle   el-tag--primary">
+                <!-- <div class="footerTitle   el-tag--primary">
                 <div>
                   <p>信息栏</p>
                 </div>
@@ -967,16 +1041,17 @@
                     <span @click="footerShows('foot')">&#9650;&#9660;</span>
                   </li>
                 </div>
-              </div> 
-                 <div class="footerTextBox"   v-if="footerShow">
+              </div>  -->
+                 <!-- <div class="footerTextBox"   v-if="footerShow">
                   <el-input
                     class="footerText"
                     type="textarea"
                     id="textarea_id"
                     v-model="logs"
                   ></el-input>
-                </div> 
+                </div>  -->
                 </div>
+              </div>
               </el-footer>
               </div> 
             </div>
@@ -998,172 +1073,162 @@
   import { Edit,CaretBottom } from '@element-plus/icons-vue'
   // import '@/utils/flexible'
   import s0 from "@/assets/img/s0.png"
+  import gc1 from "@/assets/img/gc1.png"
+  import gc2 from "@/assets/img/gc2.png"
+  import gc3 from "@/assets/img/gc3.png"
+  import wen from "@/assets/img/wen.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 sixchine from './demo/chine.vue'
-  import modelb from './vueflow/modelb.vue'
-  import vuefindex from './vueflow/index.vue'
-  import Sidebar from './vueflow/Sidebar.vue'
+  import vuefindex from './vuetree/index.vue'
+  import Sidebar from './vuetree/Sidebar.vue'
   const router = useRouter();
   let logs=ref("");
+  let tableval=ref();
   let elodingfalse=ref(false);
   let footerShow=ref(false);
   let tabName=ref("one")
+  const tabs = ['信息栏', '优化问题'];
+  const listli = ['设计变量', '约束条件', '优化目标'];
+  const activeIndex = ref(0);
+  const activeIndex2 = ref(0);
   const datatree = ref([
     {
-      label: '优化设计',
+      id:1,
+      label: '工程',
       children: [
         {
+          id:'1-1',
           label: '优化问题',
-          children: [
-            {
-              label: '优化目标',
-              children: [
-                {
-                  label: '输出',
-                },
-              ],
-            },
-            {
-              label: '设计变量',
-              children: [
-                {
-                  label: '输入1',
-                },
-                {
-                  label: '输入2',
-                },
-              ],
-            },
-          ],
+          img:gc1,
+         
         },
         {
+          id:'1-2',
           label: '分析流程',
-          children: [
-            {
-              label: '优化器',
-            },
-            {
-              label: 'Python',
-            },
-          ],
+          img:gc2,
+   
+        },
+        {
+          id:'1-3',
+          label: '优化器',
+          img:gc3
         },
       ],
     },
   
   ])
-  const treeData = ref([
-    // { 
-      // id:0,
-      // label: '优化设计',
-      // children: [
-      //   {
-      //     // id:1,
-      //     // label: '任务',
-      //     // children: [
-      //     //   {
-      //     //     label: '任务编号',
-      //     //   },
-      //     //   {
-      //     //     label: '任务名称',
-      //     //   },
-      //     //   {
-      //     //     label: '任务类型',
-      //     //   },
-      //     // ],
-      //   },
+
+  const datatree1 = ref([
+    {
+      id:2,
+      label: '优化问题组件',
+      img:'',
+      children: [
         {
-          id:2,
+          id:'2_1',
           label: '优化问题',
-          children: [
-            {
-              label: '问题设定',
-            },
-            {
-              label: '优化目标',
-            },
-            {
-              label: '设计变量',
-            },
-            {
-              label: '约束条件',
-            },
-          ],
+          img:"wen.png",
+         
+        },
+      ],
+    },
+    {
+      id:3,
+      label: '学科分析组件',
+      img:'',
+      children: [
+        {
+          id:'3-1',
+          label: 'CATIA',
+          img:'xuek1.png',
         },
         {
-          id:3,
-          label: '优化模型',
-          children: [
-            {
-              label: '代理模型',
-            },
-            {
-              label: '优化算法',
-            },
-            {
-              label: '加点方法',
-            },
-          
-          ],
+          id:'3-2',
+          label: 'Excel',
+          img:'xuek2.png',
+   
         },
         {
-          id:4,
-          label: '优化运行',
-          children: [
-            {
-              label: '任务提交',
-            },
-            {
-              label: '优化监控',
-            },
-          
-          ],
+          id:'3-3',
+          label: 'Feko',
+          img:'xuek3.png'
         },
-        
         {
-          id:5,
-          label: '优化结果',
-          children: [
-            {
-              label: '可视化',
-            },
-            {
-              label: '查看报告',
-            },
-            {
-              label: '导出报告',
-            },
-          
-          ],
+          id:'3-4',
+          label: 'Fluent',
+          img:'xuek4.png',
+         
         },
         {
-          id:6,
-          label: '数据库管理',
-          children: [
-            {
-              label: '任务检索',
-            },
-          ],
+          id:'3-5',
+          label: 'HCFD',
+          img:'xuek5.png',
+   
         },
-       
-      
-    //   ],
-    // },
+        {
+          id:'3-6',
+          label: 'Matlab',
+          img:"xuek6.png"
+        },
+        {
+          id:'3-7',
+          label: 'Nastran',
+          img:'xuek7.png',
+         
+        },
+        {
+          id:'3-8',
+          label: 'Python',
+          img:'xuek8.png',
+   
+        },
+        {
+          id:'3-9',
+          label: 'AirfoilAero',
+          img:'xuek9.png'
+        },
+      ],
+    },
+    {
+      id:4,
+      label: '优化器组件',
+      img:'',
+      children: [
+        {
+          id:'4-1',
+          label: '进化优化器',
+          img:'youh1.png',
+         
+        },
+        {
+          id:'4-2',
+          label: '代理优化器',
+          img:'youh2.png',
+   
+        },
+        {
+          id:'4-3',
+          label: '梯度优化器',
+          img:'youh3.png',
+        },
+      ],
+    },
   
   ])
-  
-  
   let  defaultExpandedArr=ref([]);
   const defaultProps = {
     children: 'children',
     label: 'label',
   }
-  treeData.value.forEach((item) => {
-    defaultExpandedArr.value.push(item.id);
-        });
+
+  // treeData.value.forEach((item) => {
+  //   defaultExpandedArr.value.push(item.id);
+  //       });
   const activeName = ref('Three')
+  const activeName1 = ref('message')
   let active = ref('');
   let tabactive=ref("");
   let checkbox=ref(false)
@@ -1378,28 +1443,6 @@
       address:'serrrrrrr'
       
     },
-    {
-      name:"true",
-      date: '2016-05-03',
-      device: '升阻比',
-      z: '增大',
-      q:1.0,
-      cai:false,
-      yin:1.0,
-      address:'serrrrrrr'
-      
-    },
-    {
-      name:"false",
-      date: '2016-05-03',
-      device: '升阻比',
-      z: '增大',
-      q:1.0,
-      cai:false,
-      yin:1.0,
-      address:'serrrrrrr'
-      
-    },
   ])
   const tasktable = ref([
   {
@@ -1434,6 +1477,13 @@
     }
     dialogcolse()
   }
+  //表格点击事件
+  const handleEdit = (row) => {
+  console.log('编辑后的数据:', row);
+  // 在这里处理数据保存逻辑,例如发送请求到后端更新数据
+};
+  const footerClick = (tab, event) => {
+}
   // 关闭所有弹窗
   const  dialogcolse=()=>{
     dialog.value.newdialog = false;
@@ -1521,6 +1571,27 @@
   const targetclick=()=>{
     console.log(tableData.value)
   }
+  //新增
+  const onAddItem=()=>{
+    let tablevalnum=Number(tableval.value)
+
+    if(activeIndex2.value==0){
+      for (let i = 0; i < tablevalnum; i++) {
+        designtable.value.push({
+                name:"",
+                date: '',
+                device: '',
+                z: '',
+                q:'',
+                cai:'',
+                yin:'',
+                address:''
+                
+                })
+      }
+    }
+
+  }
   // 日志框
      // 日志的文本框
      const  footerShows=(evt)=>{
@@ -1542,8 +1613,7 @@
       padding: 5px 20px;
       font-size: 20px;
       height: 25px !important;
-      z-index: 99;
-      background-color: #fff;
+      z-index: 99;;
       border-radius: 5px 5px 0px 0px;
       // bottom: 160px;
       // position: absolute;
@@ -1576,6 +1646,105 @@
     padding: 2px;
   }
   //没有子节点
-  
-  
+  </style>
+  <style>
+    .el-treeicon .el-tree-node__expand-icon.is-leaf{
+   display: none !important;
+  }
+  .custom-text{
+    font-family: Inter, Inter;
+    font-weight: 600;
+    font-size: 16px;
+    color: #383838;
+    line-height: 24px;
+    text-align: left;
+    font-style: normal;
+    text-transform: none;
+  } 
+  .el-tree  .el-tree-node__children  .custom-text{
+  font-size: 13px; /* 这里设置为20px,你可以根据需求调整大小 */
+  font-weight: 400;
+}
+/* .el-tree  .el-tree-node.is-current>.el-tree-node__content img{
+ display: none; 
+} */
+ .custom-tree1 > .el-tree-node > .el-tree-node__content >div img{
+      display: none; /* 隐藏一级节点复选框 */
+    }
+ .footerTitle{
+      background: #9FCDFF;
+border-radius: 0px 0px 0px 0px;
+    }
+    .footer-tab .el-tabs__item{
+      color: #383838;
+    }
+    .footerTitle .active {
+  background-color: #f0f0f0;
+}
+.youhualog{
+  width: 100%;
+  height: 178px;
+  overflow-y: auto;
+}
+.youhualog .active2 {
+  background-color: #f0f0f0;
+}
+.youhualog ul{
+width: 320px;
+display: flex;
+}
+.youhualog ul li{ 
+  flex: 1;
+  background: #DFDFDF ;
+  border: 1px solid #2267B1;
+  font-size: 14px;
+
+}
+.footer-content{
+  padding: 15px 24px;
+  border: 1px solid #2267B1;
+  margin-right: 119px;
+}
+.footer-add{
+  width: 530px;
+}
+.dibu{
+  margin-top: 10px;
+  display: flex;
+    justify-content: flex-end;
+}
+.dibu .el-input__wrapper{
+  width: 226px;
+}
+.dibu .btncolor{
+  margin-top: 2px;
+    height: 27px;
+  background: #FFFFFF;
+box-shadow: 0px 2px 2px 0px #2267B1;
+border-radius: 0px 0px 0px 0px;
+border: 1px solid #2267B1;
+}
+.el-table td.el-table__cell div .el-input__wrapper{
+  box-shadow: none !important;
+  padding: 0;
+}
+.el-table .el-table__cell{
+  padding: 0;
+}
+.gooterpading{
+  border: 1px solid #2267B1;
+}
+.el-table th .cell{
+  background:#D8D8D8;
+}
+.el-table .cell{
+  font-size: 12px;
+}
+.el-table td.el-table__cell div{
+  height: 24px;
+    overflow: hidden;
+}
+.el-table td.el-table__cell, .el-table th.el-table__cell.is-leaf,.eldesign{
+  border: 1px solid #000000;
+}
   </style>

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

@@ -8,6 +8,7 @@ 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>

+ 1 - 2
src/views/vueflow/useDnD.js

@@ -30,7 +30,7 @@ function imagefun(){
     }else if(nid==3){
       return datas = {label:'优化器', image:f32}
     }else{
-      return datas = {label:'模版', image:f41}
+     // return datas = {label:'模版', image:f41}
     }
 
   }
@@ -293,7 +293,6 @@ snodes=nodes;
         type: 'smoothstep',
         markerEnd: MarkerType.ArrowClosed,
       }
-      console.log(newedges);
       sedges.value.push(newedges)
       //sedges=edges
     }

+ 16 - 0
src/views/vuetree/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>

+ 38 - 0
src/views/vuetree/Icon.vue

@@ -0,0 +1,38 @@
+<script setup>
+defineProps({
+  name: {
+    type: String,
+    required: true,
+  },
+})
+</script>
+
+<template>
+  <svg v-if="name === 'reset'" width="16" height="16" viewBox="0 0 32 32">
+    <path d="M18 28A12 12 0 1 0 6 16v6.2l-3.6-3.6L1 20l6 6l6-6l-1.4-1.4L8 22.2V16a10 10 0 1 1 10 10Z" />
+  </svg>
+
+  <svg v-if="name === 'update'" width="16" height="16" viewBox="0 0 24 24">
+    <path
+      d="M14 20v-2h2.6l-3.2-3.2l1.425-1.425L18 16.55V14h2v6Zm-8.6 0L4 18.6L16.6 6H14V4h6v6h-2V7.4Zm3.775-9.425L4 5.4L5.4 4l5.175 5.175Z"
+    />
+  </svg>
+
+  <svg v-if="name === 'sun'" width="16" height="16" viewBox="0 0 24 24">
+    <path
+      d="M12 17q-2.075 0-3.537-1.463Q7 14.075 7 12t1.463-3.538Q9.925 7 12 7t3.538 1.462Q17 9.925 17 12q0 2.075-1.462 3.537Q14.075 17 12 17ZM2 13q-.425 0-.712-.288Q1 12.425 1 12t.288-.713Q1.575 11 2 11h2q.425 0 .713.287Q5 11.575 5 12t-.287.712Q4.425 13 4 13Zm18 0q-.425 0-.712-.288Q19 12.425 19 12t.288-.713Q19.575 11 20 11h2q.425 0 .712.287q.288.288.288.713t-.288.712Q22.425 13 22 13Zm-8-8q-.425 0-.712-.288Q11 4.425 11 4V2q0-.425.288-.713Q11.575 1 12 1t.713.287Q13 1.575 13 2v2q0 .425-.287.712Q12.425 5 12 5Zm0 18q-.425 0-.712-.288Q11 22.425 11 22v-2q0-.425.288-.712Q11.575 19 12 19t.713.288Q13 19.575 13 20v2q0 .425-.287.712Q12.425 23 12 23ZM5.65 7.05L4.575 6q-.3-.275-.288-.7q.013-.425.288-.725q.3-.3.725-.3t.7.3L7.05 5.65q.275.3.275.7q0 .4-.275.7q-.275.3-.687.287q-.413-.012-.713-.287ZM18 19.425l-1.05-1.075q-.275-.3-.275-.712q0-.413.275-.688q.275-.3.688-.287q.412.012.712.287L19.425 18q.3.275.288.7q-.013.425-.288.725q-.3.3-.725.3t-.7-.3ZM16.95 7.05q-.3-.275-.287-.688q.012-.412.287-.712L18 4.575q.275-.3.7-.288q.425.013.725.288q.3.3.3.725t-.3.7L18.35 7.05q-.3.275-.7.275q-.4 0-.7-.275ZM4.575 19.425q-.3-.3-.3-.725t.3-.7l1.075-1.05q.3-.275.713-.275q.412 0 .687.275q.3.275.288.688q-.013.412-.288.712L6 19.425q-.275.3-.7.287q-.425-.012-.725-.287Z"
+    />
+  </svg>
+
+  <svg v-if="name === 'moon'" width="16" height="16" viewBox="0 0 24 24">
+    <path
+      d="M12 21q-3.75 0-6.375-2.625T3 12q0-3.75 2.625-6.375T12 3q.35 0 .688.025q.337.025.662.075q-1.025.725-1.637 1.887Q11.1 6.15 11.1 7.5q0 2.25 1.575 3.825Q14.25 12.9 16.5 12.9q1.375 0 2.525-.613q1.15-.612 1.875-1.637q.05.325.075.662Q21 11.65 21 12q0 3.75-2.625 6.375T12 21Z"
+    />
+  </svg>
+
+  <svg v-if="name === 'log'" width="16" height="16" viewBox="0 0 24 24">
+    <path
+      d="M20 19V7H4v12h16m0-16a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16m-7 14v-2h5v2h-5m-3.42-4L5.57 9H8.4l3.3 3.3c.39.39.39 1.03 0 1.42L8.42 17H5.59l3.99-4Z"
+    />
+  </svg>
+</template>

+ 180 - 0
src/views/vuetree/Sidebar.vue

@@ -0,0 +1,180 @@
+<script setup>
+  import { ref, onMounted, reactive, } from "vue";
+  import { ElMessage, ElButton, ElDialog, ElSelect } from 'element-plus'
+  import gc1 from "@/assets/img/gc1.png"
+  import gc2 from "@/assets/img/gc2.png"
+  import gc3 from "@/assets/img/gc3.png"
+import useDragAndDrop from './useDnD'
+const { onDragStart,onDragLeave,} = useDragAndDrop()
+const datatree = ref([
+    {
+      id:1,
+      label: '工程',
+      children: [
+        {
+          id:'1-1',
+          label: '优化问题',
+          img:gc1,
+         
+        },
+        {
+          id:'1-2',
+          label: '分析流程',
+          img:gc2,
+   
+        },
+        {
+          id:'1-3',
+          label: '优化器',
+          img:gc3
+        },
+      ],
+    },
+  
+  ])
+
+  const datatree1 = ref([
+    {
+      id:2,
+      label: '优化问题组件',
+      img:'',
+      children: [
+        {
+          id:'2_1',
+          label: '优化问题',
+          img:"wen.png",
+         
+        },
+      ],
+    },
+    {
+      id:3,
+      label: '学科分析组件',
+      img:'',
+      children: [
+        {
+          id:'3-1',
+          label: 'CATIA',
+          img:'xuek1.png',
+        },
+        {
+          id:'3-2',
+          label: 'Excel',
+          img:'xuek2.png',
+   
+        },
+        {
+          id:'3-3',
+          label: 'Feko',
+          img:'xuek3.png'
+        },
+        {
+          id:'3-4',
+          label: 'Fluent',
+          img:'xuek4.png',
+         
+        },
+        {
+          id:'3-5',
+          label: 'HCFD',
+          img:'xuek5.png',
+   
+        },
+        {
+          id:'3-6',
+          label: 'Matlab',
+          img:"xuek6.png"
+        },
+        {
+          id:'3-7',
+          label: 'Nastran',
+          img:'xuek7.png',
+         
+        },
+        {
+          id:'3-8',
+          label: 'Python',
+          img:'xuek8.png',
+   
+        },
+        {
+          id:'3-9',
+          label: 'AirfoilAero',
+          img:'xuek9.png'
+        },
+      ],
+    },
+    {
+      id:4,
+      label: '优化器组件',
+      img:'',
+      children: [
+        {
+          id:'4-1',
+          label: '进化优化器',
+          img:'youh1.png',
+         
+        },
+        {
+          id:'4-2',
+          label: '代理优化器',
+          img:'youh2.png',
+   
+        },
+        {
+          id:'4-3',
+          label: '梯度优化器',
+          img:'youh3.png',
+        },
+      ],
+    },
+  
+  ])
+  const getImgPath = (url) => {
+    return new URL(`../../assets/img/${url}`, import.meta.url).href
+  }
+  const defaultProps = {
+    children: 'children',
+    label: 'label',
+  }
+  const handleNodeClick = (data) => {
+  }
+</script>
+
+<template>
+<div class="left_main">
+
+<div class="left_main_content el-treeicon">
+  <el-tree :data="datatree"  class="custom-tree"  default-expand-all  :props="defaultProps" @node-click="handleNodeClick"  >
+    <template #default="{ node, data }">
+          <div   @dragstart="onDragStart($event, 'default',data.id)">
+            <img :src="data.img" class="custom-image" />
+            <span class="custom-text">
+              {{ node.label }}
+            </span>
+          </div>
+        </template>
+  </el-tree>
+ <el-tree :data="datatree1"  class="custom-tree1" default-expand-all  :props="defaultProps" @node-click="handleNodeClick">
+    <template #default="{ node, data }">
+          <div  @dragstart="onDragStart($event, 'default',data.id)">
+            <img :src="getImgPath(data.img)" class="custom-image" />
+            <span class="custom-text">
+              {{ node.label }} 
+            </span>
+          </div>
+        </template>
+  </el-tree> 
+</div>
+</div>
+</template>
+<style scoped>
+.moban button{
+  margin: 10px;
+}
+.moban .el-image{
+  width: 40px;}
+  .moban span{
+    display: block;
+  }
+</style>

+ 72 - 0
src/views/vuetree/eltree.vue

@@ -0,0 +1,72 @@
+<script  setup>
+import { ref, onMounted, reactive, } from "vue";
+import { VueFlow,Handle, useVueFlow,Position } from '@vue-flow/core'
+const props = defineProps({
+  node: {
+    type: Object,
+    required: true,
+  },
+  sourcePosition: {
+    type: String,
+  },
+  targetPosition: {
+    type: String,
+  },
+})
+onMounted(() => {
+});
+</script>
+<template>
+ 
+  <div>
+    <div class="custom-node icons" :id="`node-${node.id}`" >
+    <img :src="props.node.data.image" alt="节点图片" />
+    <span>{{props.node.data.label }}</span>
+  </div>
+
+  </div>
+ <Handle type="source" :position="Position.Right"  />
+  <Handle id="target-c" type="source" :position="Position.Top"  /> 
+   <Handle id="target-b" type="target"  :position="Position.Left" /> 
+  <Handle id="target-d" type="target" :position="Position.Bottom"  /> 
+</template>
+<style scoped>
+
+.icons img{
+    width: 50px;;
+
+}
+.icons span{
+  display: block;
+  font-size: 13px;
+}
+</style>
+<style>
+.vue-flow__node.draggable {
+  width: 80px !important;
+    height: 80px !important;
+    border: none;
+    background-color: rgba(0,0,0,0);
+}
+.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>

+ 226 - 0
src/views/vuetree/index.vue

@@ -0,0 +1,226 @@
+<script setup>
+import { ref } from 'vue'
+import { VueFlow, useVueFlow } from '@vue-flow/core'
+import { Background } from '@vue-flow/background'
+import { ControlButton, Controls } from '@vue-flow/controls'
+import { MiniMap } from '@vue-flow/minimap'
+import "./main.css";//重置样式
+  import DropzoneBackground from './DropzoneBackground.vue'
+   import eltree from './eltree.vue'
+   import useDragAndDrop from './useDnD'
+   import f11 from '@/assets/img/f11.png'
+  import { initialEdges, initialNodes } from './initial-elements.js'
+import Icon from './Icon.vue'
+
+/**
+ * `useVueFlow` provides:
+ * 1. a set of methods to interact with the VueFlow instance (like `fitView`, `setViewport`, `addEdges`, etc)
+ * 2. a set of event-hooks to listen to VueFlow events (like `onInit`, `onNodeDragStop`, `onConnect`, etc)
+ * 3. the internal state of the VueFlow instance (like `nodes`, `edges`, `viewport`, etc)
+ */
+// our dark mode toggle flag
+const dark = ref(false)
+const { onInit, onNodeDragStop, onConnect, addEdges, setViewport, toObject } = useVueFlow()
+  let vueFlowRef=ref();
+  let emit = defineEmits(['optimizerfalse']);
+  const props = defineProps({})
+  let  shopShow=ref(false);
+  let noid=ref([]);
+  let node=ref();
+  let  contextMenu=ref( {
+          shopShow: false,
+          position: { x: 0, y: 0 },
+          target: 'kong',
+        })
+  const { onDragOver, onDrop, onDragLeave, isDragOver} = useDragAndDrop();
+  const edges = ref([]);
+  const nodes = ref([]);
+  onConnect(addEdges)
+  
+  function onNodeClick(e){
+    noid.value=e.node;
+    console.log(e);
+    console.log(111111)
+    if(e.node.data.label=='优化器'){
+      console.log(e.node);
+      emit('optimizerfalse', true);
+    }
+  
+  }
+  function onContextMenu(event,node) {
+    console.log(event)
+    console.log(node)
+   // event.preventDefault();
+   if(noid.value!==null){
+  
+  
+        if (noid.value.id) {
+          document.getElementById('contextMenu').style.top = noid.value.position.y+50 + 'px';
+       document.getElementById('contextMenu').style.left = noid.value.position.x +80+ 'px';
+       document.getElementById('contextMenu').style.display = 'block';
+      shopShow.value=true;
+       event.preventDefault();
+  
+        }
+      }
+    
+      }
+      //点击左键右键内容消失
+      document.addEventListener('click', function(e) {
+    if (e.button === 0) { // 0 是左键
+       //document.getElementById('contextMenu').style.display = 'none';
+      shopShow.value=false;
+    }
+  });
+      function   onDeleteKey(event,node) {
+        // 禁用Backspace删除节点
+        console.log(event)
+        event.preventDefault();
+     
+      }
+  //删除
+  const deleteItemConfirm=()=>{
+    //const index = nodes.value.findIndex(n => n.id === noid.value.id);
+    if(noid.value.id){
+      console.log(id);
+    vueFlowRef.value.removeNodes(noid.value.id);
+    noid.value=null;
+     // nodes.value = nodes.value.filter(node => node.id !== noid.value.id);
+   //console.log(noid.value.id);
+    // resolve(true)
+    // console.log( resolve(true));
+    shopShow.value = false
+    }
+  
+  }
+
+/**
+ * This is a Vue Flow event-hook which can be listened to from anywhere you call the composable, instead of only on the main component
+ * Any event that is available as `@event-name` on the VueFlow component is also available as `onEventName` on the composable and vice versa
+ *
+ * onInit is called when the VueFlow viewport is initialized
+ */
+onInit((vueFlowInstance) => {
+  // instance is the same as the return of `useVueFlow`
+  vueFlowInstance.fitView()
+})
+
+/**
+ * onNodeDragStop is called when a node is done being dragged
+ *
+ * Node drag events provide you with:
+ * 1. the event object
+ * 2. the nodes array (if multiple nodes are dragged)
+ * 3. the node that initiated the drag
+ * 4. any intersections with other nodes
+ */
+onNodeDragStop(({ event, nodes, node }) => {
+  console.log('Node Drag Stop', { event, nodes, node })
+})
+
+/**
+ * onConnect is called when a new connection is created.
+ *
+ * You can add additional properties to your new edge (like a type or label) or block the creation altogether by not calling `addEdges`
+ */
+onConnect((connection) => {
+  addEdges(connection)
+})
+
+/**
+ * To update a node or multiple nodes, you can
+ * 1. Mutate the node objects *if* you're using `v-model`
+ * 2. Use the `updateNode` method (from `useVueFlow`) to update the node(s)
+ * 3. Create a new array of nodes and pass it to the `nodes` ref
+ */
+function updatePos() {
+  nodes.value = nodes.value.map((node) => {
+    return {
+      ...node,
+      position: {
+        x: Math.random() * 400,
+        y: Math.random() * 400,
+      },
+    }
+  })
+}
+
+/**
+ * toObject transforms your current graph data to an easily persist-able object
+ */
+function logToObject() {
+  console.log(toObject())
+}
+
+/**
+ * Resets the current viewport transformation (zoom & pan)
+ */
+function resetTransform() {
+  setViewport({ x: 0, y: 0, zoom: 1 })
+}
+
+function toggleDarkMode() {
+  dark.value = !dark.value
+}
+</script>
+
+<template>
+  <div>
+    <div id="contextMenu"   v-show="shopShow"  @click="deleteItemConfirm">删除</div>
+</div>
+  <VueFlow
+    :nodes="nodes"
+    :edges="edges"
+    :class="{ dark }"
+    class="basic-flow"
+    :default-viewport="{ zoom: 1.5 }"
+    :min-zoom="0.2"
+    :max-zoom="4"
+    @drop="onDrop"   @contextmenu.prevent="onContextMenu"
+      @keydown.delete="onDeleteKey"   @dragover="onDragOver" @dragleave="onDragLeave"  @node-click="onNodeClick">
+      <template #node-default="props">
+         <eltree  :node="props"  />
+      </template>
+    
+    <Background pattern-color="#aaa" :gap="16" /> 
+
+    <!-- <MiniMap /> -->
+
+    <Controls position="top-left">
+      <ControlButton title="Reset Transform" @click="resetTransform">
+        <Icon name="reset" />
+      </ControlButton>
+
+      <ControlButton title="Shuffle Node Positions" @click="updatePos">
+        <Icon name="update" />
+      </ControlButton>
+
+      <ControlButton title="Toggle Dark Mode" @click="toggleDarkMode">
+        <Icon v-if="dark" name="sun" />
+        <Icon v-else name="moon" />
+      </ControlButton>
+
+      <ControlButton title="Log `toObject`" @click="logToObject">
+        <Icon name="log" />
+      </ControlButton>
+    </Controls>
+  </VueFlow>
+
+</template>
+<style>
+  .vue-flow__edge {
+    text-align: left; /* 设置edges的左对齐 */
+  }
+  #contextMenu{
+    /* display: none; */
+    position: absolute;
+  background-color: #fff;
+  border-radius: 5px;
+  padding: 10px;
+  text-align: center;
+  color: black;
+  font-size: 14px;
+  font-weight: 400;
+  cursor: pointer;
+  }
+</style>

+ 69 - 0
src/views/vuetree/initial-elements.js

@@ -0,0 +1,69 @@
+import { MarkerType } from '@vue-flow/core'
+
+export const initialNodes = [
+  {
+    id: '1',
+    type: 'input',
+    data: { label: 'Node 1' },
+    position: { x: 250, y: 0 },
+    class: 'light',
+  },
+  {
+    id: '2',
+    type: 'output',
+    data: { label: 'Node 2' },
+    position: { x: 100, y: 100 },
+    class: 'light',
+  },
+  {
+    id: '3',
+    data: { label: 'Node 3' },
+    position: { x: 400, y: 100 },
+    class: 'light',
+  },
+  {
+    id: '4',
+    data: { label: 'Node 4' },
+    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',
+  },
+]

+ 79 - 0
src/views/vuetree/main.css

@@ -0,0 +1,79 @@
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/core@1.40.1/dist/style.css';
+@import 'https://cdn.jsdelivr.net/npm/@vue-flow/core@1.40.1/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;
+}
+
+.basic-flow.dark {
+    background:#2d3748;
+    color:#fffffb
+}
+
+.basic-flow.dark .vue-flow__node {
+    background:#4a5568;
+    color:#fffffb
+}
+
+.basic-flow.dark .vue-flow__node.selected {
+    background:#333;
+    box-shadow:0 0 0 2px #2563eb
+}
+
+.basic-flow .vue-flow__controls {
+    display:flex;
+    flex-wrap:wrap;
+    justify-content:center
+}
+
+.basic-flow.dark .vue-flow__controls {
+    border:1px solid #FFFFFB
+}
+
+.basic-flow .vue-flow__controls .vue-flow__controls-button {
+    border:none;
+    border-right:1px solid #eee
+}
+
+.basic-flow .vue-flow__controls .vue-flow__controls-button svg {
+    height:100%;
+    width:100%
+}
+
+.basic-flow.dark .vue-flow__controls .vue-flow__controls-button {
+    background:#333;
+    fill:#fffffb;
+    border:none
+}
+
+.basic-flow.dark .vue-flow__controls .vue-flow__controls-button:hover {
+    background:#4d4d4d
+}
+
+.basic-flow.dark .vue-flow__edge-textbg {
+    fill:#292524
+}
+
+.basic-flow.dark .vue-flow__edge-text {
+    fill:#fffffb
+}

+ 157 - 0
src/views/vuetree/nodes.vue

@@ -0,0 +1,157 @@
+<template>
+    <div class="dnd-flow" >
+      <VueFlow ref="vueFlowRef"  :class="{ dark }"
+    class="basic-flow"
+    :default-viewport="{ zoom: 1.5 }"
+    :min-zoom="0.2"
+    :max-zoom="4"  :nodes="nodes" :edges="edges"  @drop="onDrop"   @contextmenu.prevent="onContextMenu"
+      @keydown.delete="onDeleteKey"   @dragover="onDragOver" @dragleave="onDragLeave"  @node-click="onNodeClick">
+          <template #node-default="props">
+            <eltree  :node="props"  />
+      </template>
+   
+      </VueFlow>
+  
+      <!-- <Sidebar /> -->
+    <!-- 优化器 -->
+    <div id="contextMenu"   v-show="shopShow"  @click="deleteItemConfirm">删除</div>
+    </div>
+  </template>
+  
+  
+  <script setup>
+  import { ref } from 'vue'
+  import { VueFlow,  useVueFlow,Position } from '@vue-flow/core'
+  import { ControlButton, Controls } from '@vue-flow/controls'
+   import Icon from './Icon.vue'
+  import "./main.css";//重置样式
+  import DropzoneBackground from './DropzoneBackground.vue'
+  import eltree from './eltree.vue'
+  import useDragAndDrop from './useDnD'
+  import f11 from '@/assets/img/f11.png'
+   const { onConnect, addEdges, onNodesChange, onEdgesChange, applyNodeChanges, applyEdgeChanges } = useVueFlow()
+  let vueFlowRef=ref();
+  let emit = defineEmits(['optimizerfalse']);
+  const props = defineProps({})
+  let  shopShow=ref(false);
+  let noid=ref([]);
+  let node=ref();
+  let  contextMenu=ref( {
+          shopShow: false,
+          position: { x: 0, y: 0 },
+          target: 'kong',
+        })
+  const { onDragOver, onDrop, onDragLeave, isDragOver} = useDragAndDrop();
+  const edges = ref([]);
+  const nodes = ref([]);
+  onConnect(addEdges)
+  
+  function onNodeClick(e){
+    noid.value=e.node;
+    console.log(e);
+    console.log(111111)
+    if(e.node.data.label=='优化器'){
+      console.log(e.node);
+      emit('optimizerfalse', true);
+    }
+  
+  }
+  function onContextMenu(event,node) {
+    console.log(event)
+    console.log(node)
+   // event.preventDefault();
+   if(noid.value!==null){
+  
+  
+        if (noid.value.id) {
+          document.getElementById('contextMenu').style.top = noid.value.position.y+50 + 'px';
+       document.getElementById('contextMenu').style.left = noid.value.position.x +80+ 'px';
+       document.getElementById('contextMenu').style.display = 'block';
+      shopShow.value=true;
+       event.preventDefault();
+  
+        }
+      }
+    
+      }
+      //点击左键右键内容消失
+      document.addEventListener('click', function(e) {
+    if (e.button === 0) { // 0 是左键
+       //document.getElementById('contextMenu').style.display = 'none';
+      shopShow.value=false;
+    }
+  });
+      function   onDeleteKey(event,node) {
+        // 禁用Backspace删除节点
+        console.log(event)
+        event.preventDefault();
+     
+      }
+  //删除
+  const deleteItemConfirm=()=>{
+    //const index = nodes.value.findIndex(n => n.id === noid.value.id);
+    if(noid.value.id){
+    vueFlowRef.value.removeNodes(noid.value.id);
+    noid.value=null;
+     // nodes.value = nodes.value.filter(node => node.id !== noid.value.id);
+   //console.log(noid.value.id);
+    // resolve(true)
+    // console.log( resolve(true));
+    shopShow.value = false
+    }
+  
+  }
+  onNodesChange(async (changes) => {
+    const nextChanges = []
+  
+    for (const change of changes) {
+  
+      if (change.type === 'remove') {
+        const isConfirmed = noid.value.id
+        console.log(isConfirmed)
+        if (isConfirmed) {
+          nextChanges.push(change)
+        }
+      } else {
+        nextChanges.push(change)
+      }
+    }
+  
+    applyNodeChanges(nextChanges)
+  })
+  //  小图标
+  function logToObject() {
+  console.log(toObject())
+}
+
+/**
+ * Resets the current viewport transformation (zoom & pan)
+ */
+function resetTransform() {
+  setViewport({ x: 0, y: 0, zoom: 1 })
+}
+
+function toggleDarkMode() {
+  dark.value = !dark.value
+}
+  
+  </script>
+  <style>
+  .vue-flow__edge {
+    text-align: left; /* 设置edges的左对齐 */
+  }
+  #contextMenu{
+    /* display: none; */
+    position: absolute;
+  background-color: #fff;
+  border-radius: 5px;
+  padding: 10px;
+  text-align: center;
+  color: black;
+  font-size: 14px;
+  font-weight: 400;
+  cursor: pointer;
+  }
+  </style>
+  
+  

+ 355 - 0
src/views/vuetree/useDnD.js

@@ -0,0 +1,355 @@
+// import { useVueFlow,Position,MarkerType } from '@vue-flow/core';
+import { useVueFlow,Position,MarkerType} from '@vue-flow/core';
+import { ref, watch } from 'vue'
+import gc1 from '@/assets/flowimg/gc1.png'
+import gc2 from '@/assets/flowimg/gc2.png'
+import gc3 from '@/assets/flowimg/gc3.png'
+import wen from '@/assets/flowimg/wen.png'
+import xuek1 from '@/assets/flowimg/xuek1.png'
+import xuek2 from '@/assets/flowimg/xuek2.png'
+import xuek3 from '@/assets/flowimg/xuek3.png'
+import xuek4 from '@/assets/flowimg/xuek4.png'
+import xuek5 from '@/assets/flowimg/xuek5.png'
+import xuek6 from '@/assets/flowimg/xuek6.png'
+import xuek7 from '@/assets/flowimg/xuek7.png'
+import xuek8 from '@/assets/flowimg/xuek8.png'
+import xuek9 from '@/assets/flowimg/xuek9.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(nid);
+  
+  if(nid=='1-1'){
+    return  datas = {label: '优化问题', image:gc1}
+    }else if(nid=='1-2'){
+      return datas = {label:'分析流程', image:gc2}
+    }else if(nid=='1-3'){
+      return datas = {label:'优化器', image:gc3}
+    }else if(nid=='2_1'){
+      return datas = {label:'优化问题', image:wen}
+    }else if(nid=='3-1'){
+      return datas = {label:'CATIA', image:xuek1}
+    }else if(nid=='3-2'){
+      return datas = {label:'Excel', image:xuek2}
+    }else if(nid=='3-3'){
+      return datas = {label:'Feko', image:xuek3}
+    }else if(nid=='3-4'){
+      return datas = {label:'Fluent', image:xuek4}
+    }else if(nid=='3-5'){
+      return datas = {label:'HCFD', image:xuek5}
+    }else if(nid=='3-6'){
+      return datas = {label:'Matlab', image:xuek6}
+    }else if(nid=='3-7'){
+      return datas = {label:'Nastran', image:xuek7}
+    }else if(nid=='3-8'){
+      return datas = {label:'Python', image:xuek8}
+    }else if(nid=='3-9'){
+      return datas = {label:'AirfoilAero', image:xuek9}
+    }
+    else{
+      return;
+    }
+
+  }
+
+/**
+ * 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;
+    console.log(id);
+    console.log(1234667)
+    if (event.dataTransfer) {
+      event.dataTransfer.setData('application/vueflow', type)
+      event.dataTransfer.effectAllowed = 'move'
+    }
+
+    draggedType.value = type
+   // draggedType.value = 'smoothstep'
+    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: f11},
+      id: "node_01",
+      position: {x:245, y: 317},
+      // type: "default",
+      sourcePosition: Position.Right,
+      targetPosition: Position.Left, 
+
+      },
+      {
+      data:{label: '优化器', image: f32},
+      id: "node_02",
+      position: {x: 435, y: 317},
+      // type: "default",
+      sourcePosition: Position.Right,
+      targetPosition: Position.Left, 
+      class: 'light',
+   
+      },
+      {
+      data:{label: 'Rosenbank', image: f33},
+      id: "node_03",
+      position: {x: 630, y: 317},
+      // type: "default",
+     // type: "default",
+      sourcePosition: Position.Right,
+      targetPosition: Position.Left, 
+      // sourcePosition: Position.Top,
+      // targetPosition: Position.Bottom, 
+     
+      },
+      {
+      data:{label: '结束', image: f12},
+      id: "node_04",
+      position: {x: 804, y: 317},
+      // type: "default",
+      sourcePosition: Position.Right,
+      targetPosition: Position.Left, 
+      },
+      {
+      data:{label: '输入1', image: f21},
+      id: "node_05",
+      position: {x: 435, y: 146},
+      // type: "default",
+      draggable: true, 
+      sourcePosition: Position.Top,
+      targetPosition: Position.Bottom, 
+   
+      },
+      {
+      data:{label: '输入2', image: f21},
+      id: "node_06",
+      position: {x:804, y: 146},
+      //type: "default",//default
+      sourcePosition: Position.Top,
+      targetPosition: Position.Bottom, 
+      },
+      {
+      data:{label: '输出', image: f22},
+      id: "node_07",
+      position: {x: 630, y: 519},
+      //type: "default",
+      sourceHandle: 'Top',
+      sourcePosition: Position.Bottom,
+      targetPosition: Position.Top, 
+      },
+      
+      ]);
+      const edges = ref([
+      {
+        id: 'e1->2',
+        source: 'node_01',
+        target: 'node_02',
+        label: '按照我的来',
+        type: 'straight',
+        markerEnd: {
+          type: MarkerType.ArrowClosed,
+        },
+        // id: 'e1->2',
+        // source: 'node_01',
+        // target: 'node_02',
+        // type: 'straight',
+        // markerEnd: MarkerType.ArrowClosed,
+
+      },
+      {
+        id: 'e2->3',
+        source: 'node_02',
+        target: 'node_03',
+        type: 'straight',
+       // markerEnd: MarkerType.ArrowClosed,
+      //   markerEnd: {
+      //     type: MarkerType.ArrowClosed,
+      //     color: 'red',
+      // },
+      markerEnd: {
+        tagName: MarkerType.ArrowClosed,
+        width: 20,
+        height: 20,
+      },
+        //type: 'output',
+        // style: {
+        //   stroke: '#FF0000',
+        //   markerEnd: MarkerType.ArrowClosed,
+        // },
+      },
+      {
+        id: 'e3->4',
+        source: 'node_03',
+        target: 'node_04',
+        type: 'straight' ,
+        markerEnd: "arrow" // 或者使用 " arrowhead"
+
+
+      },
+      {
+        id: 'e4->5',
+        source: 'node_05',
+        target: 'node_03',
+        type: 'straight',
+        animated: true ,
+        sourceHandle: 'Top',
+        targetHandle:'Bottom',
+        markerEnd: MarkerType.ArrowClosed,
+
+      },
+      {
+        id: 'e5->6',
+        source: 'node_06',
+        target: 'node_03',
+        type: 'straight',
+         animated: true,
+        // source: 'handle-bottom',
+        // target: 'handle-top',
+        sourceHandle: 'Top',
+        targetHandle:'Bottom',
+        tagName: MarkerType.ArrowClosed,
+
+      
+      },
+      {
+        id: 'e6->7',
+        source: 'node_03',
+        target: 'node_07',
+        // type: 'straight',
+        type: 'straight',
+        animated: true,
+        sourceHandle: 'Top',
+        targetHandle:'Bottom',
+        markerEnd: MarkerType.ArrowClosed,
+      },
+      ]);
+snodes=nodes;
+ sedges=edges;
+    }else{
+      snodes.value=[];
+      sedges.value=[];
+      const newNode = {
+        id: nodeId,
+        type: draggedType.value,
+        position,
+        data: image1,
+      }
+      console.log(newNode);
+      snodes.value.push(newNode)
+      const newedges = {
+        type: 'smoothstep',
+        markerEnd: MarkerType.ArrowClosed,
+      }
+      sedges.value.push(newedges)
+      //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,
+  }
+}