index.vue 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624
  1. <template>
  2. <VueFlow ref="vueFlowRef" v-model:nodes="nodes" v-model:edges="edges" :class="{ dark }"
  3. class="basic-flow"
  4. style="background-image: url('src/assets/flowimg/surromdao.png'); background-position: center; background-repeat: no-repeat;"
  5. :default-viewport="{ zoom: 1.5 }" :min-zoom="0.2" :max-zoom="2.5" @drop="onDrop1"
  6. @node-contextmenu="onNodeContextMenu"
  7. @dragover="onDragOver" @dragleave="onDragLeave" @edge-click="onEdgeClick" @node-double-click="onNodeDoubleClick"
  8. @node-click="onNodeClick" @edge-double-click="onEdgeDoubleClick">
  9. <!-- 自定义节点类型为default的节点 -->
  10. <template #node-default="props">
  11. <eltree :node="props" />
  12. </template>
  13. <!-- 自定义节点类型为group的节点 -->
  14. <template #node-group="props">
  15. <eltreeGroup :node="props" />
  16. </template>
  17. <Background pattern-color="#aaa" :gap="16"
  18. />
  19. <!-- <MiniMap /> @input="handleUpdate"-->
  20. <Panel :position="'right'" style="display: none;">
  21. <div class="field">
  22. <div>
  23. <label for="label">Label:</label>
  24. <input id="label" v-model.lazy="labelname" /></div>
  25. <button @click="handleUpdate" class="lableaniu">确定</button>
  26. </div>
  27. <!-- <div> -->
  28. <!-- <button class="remove" @click="removeNode(event)">N</button>
  29. <button class="remove" @click="removeEdge(event)">E</button>
  30. <button class="remove" @click="removeall(event)">all</button>
  31. </div> -->
  32. <!-- <button @click="onSelection()" class="lableaniu">获取</button> -->
  33. </Panel>
  34. <Controls position="top-left">
  35. <ControlButton title="重置" @click="resetTransform">
  36. <Icon name="reset" />
  37. </ControlButton>
  38. <ControlButton title="背景切换" @click="toggleDarkMode">
  39. <Icon v-if="dark" name="sun" />
  40. <Icon v-else name="moon" />
  41. </ControlButton>
  42. <ControlButton title="保存" @click="logToObject1">
  43. <!-- <Icon name="log" /> -->
  44. <el-icon :color="iconcolor"><UploadFilled /></el-icon>
  45. </ControlButton>
  46. <ControlButton title="删除节点" @click="removeNode()">
  47. <el-icon :color="iconcolor"><DocumentDelete /></el-icon>
  48. </ControlButton>
  49. <ControlButton title="删除线" @click="removeEdge()">
  50. <el-icon :color="iconcolor"><Crop /></el-icon>
  51. </ControlButton>
  52. <ControlButton title="清空全部" @click="confirmDelete()">
  53. <el-icon :color="iconcolor"><DeleteFilled /></el-icon>
  54. </ControlButton>
  55. </Controls>
  56. <el-dialog v-model="changeNameshow" align-center :modal="false" :close-on-click-modal="false"
  57. :append-to-body="true" draggable :fullscreen="false" :modal-append-to-body="false" modal-class="summary-dlg"
  58. width="400" class="dialog_class bgcolor colortext tianjia sel">
  59. <template #header="{ titleId, titleClass }">
  60. <div class="my-header ">
  61. <h4 :id="titleId" :class="titleClass">修改名称</h4>
  62. </div>
  63. </template>
  64. <div style="margin-top: 20px;padding: 20px;">
  65. <el-form :model="changeName" label-width="100px" class="demo-ruleForm">
  66. <el-form-item label="新名称:" prop="name">
  67. <el-input v-model="changeName.name" placeholder="请输入名称" maxlength="20"></el-input>
  68. </el-form-item>
  69. </el-form>
  70. </div>
  71. <template #footer>
  72. <div class="dialog-footer">
  73. <el-button @click="changeNameshow = false">取 消</el-button>
  74. <el-button type="primary" @click="handleUpdate">确 定</el-button>
  75. </div>
  76. </template>
  77. </el-dialog>
  78. <!-- 双击线段 -->
  79. <el-dialog v-model="dataflowshow" align-center :modal="false" :close-on-click-modal="false"
  80. :append-to-body="true" draggable :fullscreen="false" :modal-append-to-body="false" modal-class="summary-dlg"
  81. width="500" class=" bgcolor colortext tianjia sel">
  82. <template #header="{ titleId, titleClass }">
  83. <div class="my-header ">
  84. <h4 :id="titleId" :class="titleClass">数据流</h4>
  85. </div>
  86. </template>
  87. <div style="margin-top: 5px;padding: 10px 35px;">
  88. <div v-if="datacontent === '1'">
  89. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  90. <el-checkbox v-model="checkAll"
  91. :indeterminate="isIndeterminate"
  92. @change="handlecheckAllchange">全选</el-checkbox>
  93. <div class="eldesign classtable">
  94. <el-table :data="youhuaFFDtable" border :show-header="false">
  95. <el-table-column
  96. type="index"
  97. label=""
  98. ></el-table-column>
  99. <el-table-column prop="steamflag" width="55">
  100. <template #default="{ row }">
  101. <el-checkbox
  102. :false-label="0"
  103. :true-label="1"
  104. v-model="row.steamflag"
  105. @change="handlecheckFlagchange"></el-checkbox>
  106. </template>
  107. </el-table-column>
  108. <el-table-column prop="name" label="" ></el-table-column>
  109. </el-table>
  110. </div>
  111. </el-card>
  112. </div>
  113. <div v-if="datacontent === '2'">
  114. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  115. <el-checkbox v-model="checkAll"
  116. :indeterminate="isIndeterminate"
  117. @change="handlecheckAllchange">全选</el-checkbox>
  118. <div class="eldesign classtable">
  119. <el-table :data="youhuaCSTtable" border :show-header="false">
  120. <el-table-column
  121. type="index"
  122. label=""
  123. ></el-table-column>
  124. <el-table-column prop="steamflag" width="55">
  125. <template #default="{ row }">
  126. <el-checkbox
  127. :false-label="0"
  128. :true-label="1"
  129. v-model="row.steamflag"
  130. @change="handlecheckFlagchange"></el-checkbox>
  131. </template>
  132. </el-table-column>
  133. <el-table-column prop="name" label="" ></el-table-column>
  134. </el-table>
  135. </div>
  136. </el-card>
  137. </div>
  138. <div v-if="datacontent === '3'">
  139. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  140. <el-checkbox v-model="checkAll"
  141. :indeterminate="isIndeterminate"
  142. @change="handlecheckAllchange">全选</el-checkbox>
  143. <div class="eldesign classtable">
  144. <el-table :data="ADflowyouhuatable" border :show-header="false">
  145. <el-table-column
  146. type="index"
  147. label=""
  148. ></el-table-column>
  149. <el-table-column prop="steamflag" width="55">
  150. <template #default="{ row }">
  151. <el-checkbox
  152. :false-label="0"
  153. :true-label="1"
  154. v-model="row.steamflag"
  155. @change="handlecheckFlagchange"></el-checkbox>
  156. </template>
  157. </el-table-column>
  158. <el-table-column prop="name" label="" show-overflow-tooltip></el-table-column>
  159. <el-table-column prop="steamtype">
  160. <template #default="{ row }">
  161. <el-select v-model="row.steamtype">
  162. <el-option
  163. v-for="item in steamtypeoptions"
  164. :key="item.value"
  165. :label="item.label"
  166. :value="item.value"
  167. />
  168. </el-select>
  169. </template>
  170. </el-table-column>
  171. </el-table>
  172. </div>
  173. </el-card>
  174. </div>
  175. <div v-if="datacontent === '4'">
  176. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  177. <el-checkbox v-model="checkAll"
  178. :indeterminate="isIndeterminate"
  179. @change="handlecheckAllchange">全选</el-checkbox>
  180. <div class="eldesign classtable">
  181. <el-table :data="Xfoilyouhuatable" border :show-header="false">
  182. <el-table-column
  183. type="index"
  184. label=""
  185. ></el-table-column>
  186. <el-table-column prop="steamflag" width="55">
  187. <template #default="{ row }">
  188. <el-checkbox
  189. :false-label="0"
  190. :true-label="1"
  191. v-model="row.steamflag"
  192. @change="handlecheckFlagchange"></el-checkbox>
  193. </template>
  194. </el-table-column>
  195. <el-table-column prop="name" label="" show-overflow-tooltip></el-table-column>
  196. <el-table-column prop="steamtype">
  197. <template #default="{ row }">
  198. <el-select v-model="row.steamtype">
  199. <el-option
  200. v-for="item in steamtypeoptions"
  201. :key="item.value"
  202. :label="item.label"
  203. :value="item.value"
  204. />
  205. </el-select>
  206. </template>
  207. </el-table-column>
  208. </el-table>
  209. </div>
  210. </el-card>
  211. </div>
  212. <div v-if="datacontent === '5'">
  213. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  214. <el-checkbox v-model="checkAll"
  215. :indeterminate="isIndeterminate"
  216. @change="handlecheckAllchange">全选</el-checkbox>
  217. <div class="eldesign classtable">
  218. <el-table :data="ADflowMathfunctable" border :show-header="false">
  219. <el-table-column
  220. type="index"
  221. label=""
  222. ></el-table-column>
  223. <el-table-column prop="steamflag" width="55">
  224. <template #default="{ row }">
  225. <el-checkbox
  226. :false-label="0"
  227. :true-label="1"
  228. v-model="row.steamflag"
  229. @change="handlecheckFlagchange"></el-checkbox>
  230. </template>
  231. </el-table-column>
  232. <el-table-column prop="name" label="" show-overflow-tooltip></el-table-column>
  233. <el-table-column prop="steamtype">
  234. <template #default="{ row }">
  235. <el-select v-model="row.steamtype">
  236. <el-option
  237. v-for="item in steamtypeoptions"
  238. :key="item.value"
  239. :label="item.label"
  240. :value="item.value"
  241. />
  242. </el-select>
  243. </template>
  244. </el-table-column>
  245. </el-table>
  246. </div>
  247. </el-card>
  248. </div>
  249. <div v-if="datacontent === '6'">
  250. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  251. <el-checkbox v-model="checkAll"
  252. :indeterminate="isIndeterminate"
  253. @change="handlecheckAllchange">全选</el-checkbox>
  254. <div class="eldesign classtable">
  255. <el-table :data="TacsMathFunctable" border :show-header="false">
  256. <el-table-column
  257. type="index"
  258. label=""
  259. ></el-table-column>
  260. <el-table-column prop="steamflag" width="55">
  261. <template #default="{ row }">
  262. <el-checkbox
  263. :false-label="0"
  264. :true-label="1"
  265. v-model="row.steamflag"
  266. @change="handlecheckFlagchange"></el-checkbox>
  267. </template>
  268. </el-table-column>
  269. <el-table-column prop="name" label="" show-overflow-tooltip></el-table-column>
  270. <el-table-column prop="steamtype">
  271. <template #default="{ row }">
  272. <el-select v-model="row.steamtype">
  273. <el-option
  274. v-for="item in steamtypeoptions"
  275. :key="item.value"
  276. :label="item.label"
  277. :value="item.value"
  278. />
  279. </el-select>
  280. </template>
  281. </el-table-column>
  282. </el-table>
  283. </div>
  284. </el-card>
  285. </div>
  286. <div v-if="datacontent === '7'">
  287. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  288. <el-checkbox v-model="checkAll"
  289. :indeterminate="isIndeterminate"
  290. @change="handlecheckAllchange">全选</el-checkbox>
  291. <div class="eldesign classtable">
  292. <el-table :data="youhuaTACStable" border :show-header="false">
  293. <el-table-column
  294. type="index"
  295. label=""
  296. ></el-table-column>
  297. <el-table-column prop="steamflag" width="55">
  298. <template #default="{ row }">
  299. <el-checkbox
  300. :false-label="0"
  301. :true-label="1"
  302. v-model="row.steamflag"
  303. @change="handlecheckFlagchange"></el-checkbox>
  304. </template>
  305. </el-table-column>
  306. <el-table-column prop="name" label="" ></el-table-column>
  307. </el-table>
  308. </div>
  309. </el-card>
  310. </div>
  311. <div v-if="datacontent === '8'">
  312. <el-card :shadow="none" style="min-height: 240px; max-height: 480px;">
  313. <el-checkbox v-model="checkAll"
  314. :indeterminate="isIndeterminate"
  315. @change="handlecheckAllchange">全选</el-checkbox>
  316. <div class="eldesign classtable">
  317. <el-table :data="MathFuncyouhuatable" border :show-header="false">
  318. <el-table-column
  319. type="index"
  320. label=""
  321. ></el-table-column>
  322. <el-table-column prop="steamflag" width="55">
  323. <template #default="{ row }">
  324. <el-checkbox
  325. :false-label="0"
  326. :true-label="1"
  327. v-model="row.steamflag"
  328. @change="handlecheckFlagchange"></el-checkbox>
  329. </template>
  330. </el-table-column>
  331. <el-table-column prop="name" label="" show-overflow-tooltip></el-table-column>
  332. <el-table-column prop="steamtype">
  333. <template #default="{ row }">
  334. <el-select v-model="row.steamtype">
  335. <el-option
  336. v-for="item in steamtypeoptions"
  337. :key="item.value"
  338. :label="item.label"
  339. :value="item.value"
  340. />
  341. </el-select>
  342. </template>
  343. </el-table-column>
  344. </el-table>
  345. </div>
  346. </el-card>
  347. </div>
  348. </div>
  349. <template #footer>
  350. <div class="dialog-footer">
  351. <el-button @click="dataflowshow = false">取 消</el-button>
  352. <el-button type="primary" @click="confirmselection();dataflowshow = false ">确 定</el-button>
  353. </div>
  354. </template>
  355. </el-dialog>
  356. </VueFlow>
  357. <div class="dnd-flow">
  358. <!-- <div id="contextMenu" @click="deleteItemConfirm">删除</div> -->
  359. </div>
  360. </template>
  361. <script setup>
  362. import { ref, markRaw,inject } from 'vue'
  363. import { VueFlow,Panel, useVueFlow, MarkerType} from '@vue-flow/core'
  364. import { ElMessage, ElButton, ElDialog, ElSelect, ElMessageBox} from 'element-plus'
  365. import {
  366. DocumentDelete,
  367. Delete,
  368. UploadFilled,
  369. Histogram,
  370. DeleteFilled,
  371. Crop,
  372. } from '@element-plus/icons-vue'
  373. import { useRoute } from 'vue-router';
  374. import { request, uploadFile } from "@/utils/request";
  375. import { Background } from '@vue-flow/background'
  376. import { ControlButton, Controls } from '@vue-flow/controls'
  377. import { initialEdges, initialNodes } from './modeljs.js'
  378. import { MiniMap } from '@vue-flow/minimap'
  379. import "./main.css";//重置样式
  380. import DropzoneBackground from './DropzoneBackground.vue'
  381. import eltree from './eltree.vue'
  382. import eltreeGroup from './eltreeGroup.vue'
  383. import CustomEdge from './CustomEdge.vue';
  384. import useDragAndDrop from './useDnD';
  385. import f11 from '@/assets/img/f11.png'
  386. import r2 from '@/assets/img/r2.png'
  387. import html2canvas from 'html2canvas';
  388. import Icon from './Icon.vue'
  389. import { formatTime } from '@/js/lindex.js';
  390. import emitter from "@/utils/emitter";
  391. // import func from 'vue-temp/vue-editor-bridge.js';
  392. const dark = ref(false)
  393. let datatree=ref();
  394. const route = useRoute();
  395. const { onInit, onNodeDragStop, onNodeContextMenu, onConnect, addEdges, setViewport, toObject,addNodes,updateEdgeData,onConnectStart} = useVueFlow()
  396. let vueFlowRef = ref();
  397. let emit = defineEmits(['optimizerfalse']);
  398. let mergedObj=ref();
  399. let labelname=ref();
  400. let iconcolor=ref('#000')
  401. const props = defineProps({
  402. optimizer: {
  403. type: Boolean,
  404. },
  405. jboptimizer: {
  406. type: Boolean,
  407. },
  408. Xfoil: {
  409. type: Boolean,
  410. },
  411. // color1: {
  412. // type: String,
  413. // },
  414. })
  415. let newobj=ref({
  416. name:'',
  417. description:'',
  418. })
  419. let nodesitem=ref([]);
  420. let linenum=ref(1);
  421. let bgcolor=ref();
  422. let linecolor=ref('#2267B1')
  423. let pid=ref('');
  424. let newroter=ref();
  425. let vueflowimg=ref('');
  426. const shopShow = ref(false);
  427. // 选中节点
  428. let noid = ref([]);
  429. let Edgeid = ref();
  430. let seledge=ref(null);
  431. let djshow=ref(false);
  432. let node = ref();
  433. let contextMenu = ref({
  434. position: { x: 0, y: 0 },
  435. target: 'kong',
  436. })
  437. let Nested=ref([]);
  438. let Nested2=ref([]);
  439. let nnum=ref(0);
  440. const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop();
  441. const edges = ref([]);
  442. const nodes = ref([]);
  443. const changeNameshow = ref(false);
  444. const changeName = ref({
  445. name: '',
  446. })
  447. // 旧数据存储
  448. let prevNodes = [...nodes.value];
  449. let prevEdges = [...edges.value];
  450. // 监听节点变化
  451. watch(nodes, (newNodes) => {
  452. const deletedNodes = prevNodes.filter((node) => !newNodes.some((n) => n.id === node.id));
  453. if (deletedNodes.length > 0) {
  454. console.log("Deleted Nodes:", deletedNodes);
  455. // 处理节点删除逻辑
  456. }
  457. prevNodes = [...newNodes];
  458. }, { deep: true });
  459. // 监听连线变化
  460. watch(edges, (newEdges) => {
  461. const deletedEdges = prevEdges.filter((edge) => !newEdges.some((e) => e.id === edge.id));
  462. if (deletedEdges.length > 0) {
  463. console.log("Deleted Edges:", deletedEdges);
  464. // 处理连线删除逻辑
  465. }
  466. prevEdges = [...newEdges];
  467. }, { deep: true });
  468. onNodeContextMenu((e) => {
  469. noid.value = e.node;
  470. changeName.value.name = e.node.data.label;
  471. changeNameshow.value = true;
  472. })
  473. // 监听连接开始,提前取消选中的线段
  474. onConnectStart(() => {
  475. cleanEdgeselect();
  476. });
  477. // 线的类型 process-逻辑线 data-数据线
  478. let lineType = ref('process');
  479. // 线序号
  480. let linecount = ref(0);
  481. onConnect((connection) => {
  482. console.log('线连接',connection);
  483. // 创建唯一的边ID(由源节点和目标节点组成)
  484. const edgeId = `${lineType.value}-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}`;
  485. connection.id = edgeId; // 自定义 ID
  486. connection.type = 'smoothstep';// smoothstep straight
  487. connection.zIndex = lineType.value === 'process' ? 10 : 5; // 逻辑流在上,数据流在下
  488. connection.interactionWidth = lineType.value === 'process' ? 5 : 20; // 降低逻辑流窄线判定范围,避免二者重叠无法判定
  489. if(lineType.value === 'process'){
  490. connection.markerEnd = MarkerType.ArrowClosed;
  491. }else if(lineType.value === 'data'){
  492. connection.markerEnd = {
  493. type: MarkerType.ArrowClosed,
  494. width: 6, // 设置宽度(箭头大小)
  495. height: 6, // 设置高度(箭头大小)实测长宽一样才生效
  496. color: linecolor.value, // 设置颜色
  497. };
  498. }
  499. // connection.markerEnd = lineType.value === "data" ? "" : MarkerType.ArrowClosed;
  500. connection.color=linecolor.value;
  501. // connection.label = '这是一条注释';
  502. connection.style = { strokeWidth:linenum.value ,stroke:linecolor.value};
  503. // 连接数据流线前应先连接逻辑流
  504. // if(lineType.value === 'data'){
  505. // const processEdgeId = `process-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}`;
  506. // const hasProcessEdge = edges.value.some(edge => edge.id === processEdgeId);
  507. // if(!hasProcessEdge){
  508. // ElMessage({
  509. // message:'请先连接逻辑流连线!',
  510. // type:'error'
  511. // })
  512. // return;
  513. // }
  514. // }
  515. // 相同线删除上一条线的流
  516. const sameEdge = edges.value.find(edge => edge.id === edgeId);
  517. if(sameEdge){
  518. deleteflow(sameEdge.data.wid);
  519. }
  520. addEdges(connection);
  521. seledge.value=null;
  522. linecount.value++;
  523. const newName = `Seg${linecount.value}`;
  524. const sourceNode = vueFlowRef.value.getNode(connection.source);
  525. const targetNode = vueFlowRef.value.getNode(connection.target);
  526. // 调用 saveflow 保存数据并获取 wid
  527. saveflow(pid.value, '', newName, lineType.value, sourceNode.data.uid, targetNode.data.uid)
  528. .then((wid) => {
  529. // 更新连接线的数据
  530. const updatedData = {
  531. wid: wid,
  532. uid: newName,
  533. type: lineType.value,
  534. fromuid: sourceNode.data.uid,
  535. touid: targetNode.data.uid,
  536. };
  537. updateEdgeData(connection.id, updatedData);
  538. })
  539. .catch((error) => {
  540. console.error('保存流程失败:', error);
  541. });
  542. })
  543. //修改名称
  544. const handleUpdate = () => {
  545. if (noid.value && noid.value.data) {
  546. noid.value.data.label = changeName.value.name; // 更新名称
  547. console.log(noid.value.data.label); // 打印更新后的值
  548. } else {
  549. console.error("noid.value 或 noid.value.data 未定义"); // 错误日志
  550. }
  551. changeNameshow.value = false; // 更新后关闭对话框
  552. // noid.value.data.label = labelname;
  553. };
  554. emitter.on('child2Data', data => {
  555. datatree.value = data;
  556. console.log("datatree的值:",datatree.value);
  557. })
  558. function onNodeClick(e) {
  559. noid.value = e.node;
  560. changeName.value.name=e.node.data.label;
  561. console.log("shuju:",e.node.data);
  562. console.log("noid.value:",noid.value);
  563. console.log("changeName.value:",changeName.value.name);
  564. djshow.value = !djshow.value;
  565. // if(djshow.value){
  566. // console.log('选中');
  567. // }else{
  568. // console.log('取消选中');
  569. // }
  570. }
  571. //模块化
  572. const bgcolorfunc= (color)=>{
  573. bgcolor.value=color;
  574. if(noid.value.style!=undefined){
  575. console.log(noid.value.style);
  576. noid.value.style.backgroundColor=color;
  577. }
  578. }
  579. function onSelection(){
  580. let positionX=[];
  581. let positiony=[];
  582. for(let i=0;i<Nested.value.length;i++){
  583. // Nested2.value.push(Nested.value[i]);
  584. positionX.push(Nested.value[i].position.x)
  585. positiony.push(Nested.value[i].position.y)
  586. }
  587. let xmin=Math.min(...positionX);
  588. let ymax=Math.max(...positiony);
  589. console.log(positionX);
  590. // console.log( positionX)
  591. // console.log(44444)
  592. // console.log( positiony)
  593. nnum.value++;
  594. // let x=Math.floor(Math.random() * 91) + 10;
  595. // let y=Math.floor(Math.random() * 91) + 10;
  596. let name='模块'+nnum.value
  597. let item= {
  598. id:nnum.value.toString(),
  599. data: { label:name },
  600. position: { x:xmin , y:ymax},
  601. style: { backgroundColor: bgcolor.value, width: '200px',height: '200px' },
  602. //children: [],
  603. }
  604. if(Nested.value.length!=0){
  605. Nested2.value=[];
  606. for(let i=0;i<Nested.value.length;i++){
  607. Nested2.value.push(Nested.value[i]);
  608. }
  609. console.log(Nested2.value);
  610. nodesitem.value= Nested2.value.map(node => {
  611. if(node.parentNode==undefined){
  612. node.isParent=false;
  613. node.parentNode=item.id;
  614. console.log( node.parentNode)
  615. node.position.x= node.position.x /2;
  616. node.position.y= node.position.y/2;
  617. node.expandParent=true;
  618. //positionxy=node.position;
  619. // node.extent='parent';
  620. // return node;
  621. }
  622. return node;
  623. })
  624. }
  625. nodes.value.push(item)
  626. for(let i=0;i<nodesitem.value.length;i++){
  627. console.log(nodesitem.value[i]);
  628. nodes.value.push(nodesitem.value[i])
  629. }
  630. console.log( nodes.value);
  631. }
  632. function onNodeDoubleClick(e) {
  633. noid.value = e.node;
  634. const nowid = e.node.data.wid;
  635. console.log( e.node.data.name);
  636. if (e.node.data.name == 'optimizer') {
  637. emit('optimizerfalse',{name:'优化器',wid:nowid});
  638. }else if(e.node.data.name=="optimizer1"){
  639. emit('optimizerfalse',{name:'进化优化器',wid:nowid});
  640. }else if(e.node.data.name=="optimizer3"){
  641. emit('optimizerfalse',{name:'代理优化器',wid:nowid});
  642. }else if(e.node.data.name=="Xfoil"){
  643. emit('optimizerfalse',{name:'Xfoil',wid:nowid});
  644. }else if(e.node.data.name=="optimizer2"){
  645. emit('optimizerfalse',{name:'梯度优化器',wid:nowid});
  646. }else if(e.node.data.name=="CST"){
  647. emit('optimizerfalse',{name:'CST',wid:nowid});
  648. }else if(e.node.data.name=="ADflow"|| e.node.data.name=="RAE2822"){
  649. emit('optimizerfalse',{name:'ADflow',wid:nowid});
  650. }else if(e.node.data.name=="FFD"){
  651. emit('optimizerfalse',{name:'FFD',wid:nowid});
  652. }else if(e.node.data.name=="TACS"){
  653. emit('optimizerfalse',{name:'TACS',wid:nowid});
  654. }else if(e.node.data.name=="参数化"){
  655. emit('optimizerfalse',{name:'参数化',wid:nowid});
  656. }else if(e.node.data.name=="气动分析"){
  657. emit('optimizerfalse',{name:'气动分析',wid:nowid});
  658. }else if(onPythonlist.value.some(item => e.node.data.name.includes(item))){
  659. emit('optimizerfalse',{name:e.node.data.name,wid:nowid});
  660. }else if(e.node.data.name=="CATIA"){
  661. emit('optimizerfalse',{name:'CATIA',wid:nowid});
  662. }else if(e.node.data.name=="FSI"){
  663. emit('optimizerfalse',{name:'FSI',wid:nowid});
  664. }else if(e.node.data.name=="Flight"){
  665. emit('optimizerfalse',{name:'Flight',wid:nowid});
  666. }else if(e.node.data.name=="MathFunc"){
  667. emit('optimizerfalse',{name:'MathFunc',wid:nowid});
  668. }
  669. }
  670. let onPythonlist=ref(['Python','Branin','Rosenbrock','Rastrigin','G9','Forrester']);
  671. let previousEdge = null; // 用于保存上一个选中的边缘
  672. // 监听线
  673. function onEdgeClick(e) {
  674. console.log('Edge Click', e.edge);
  675. console.log('所有线段:',edges.value);
  676. // 如果已经有选中的边缘
  677. if (seledge.value) {
  678. // 恢复上一个选中边缘的样式
  679. if (previousEdge) {
  680. previousEdge.style = {
  681. ...previousEdge.style,
  682. stroke: previousEdge.originalColor, // 恢复原始颜色
  683. strokeWidth: previousEdge.originalWidth,// 恢复原始宽度
  684. };
  685. }
  686. }
  687. // 保存当前点击的边缘为选中边缘
  688. Edgeid.value = e.edge.id;
  689. seledge.value = e.edge;
  690. // 暂时更改当前选中边缘的样式
  691. seledge.value.originalColor = seledge.value.style.stroke; // 保存当前边缘的原始颜色
  692. seledge.value.originalWidth = seledge.value.style.strokeWidth; // 保存当前边缘的原始宽度
  693. const isProcess = e.edge.data.type === 'process';
  694. seledge.value.style = {
  695. ...seledge.value.style,
  696. stroke: isProcess ? '#2267B1' : 'rgba(255, 255, 0, 0.3)',// 设置选中边缘的颜色
  697. strokeWidth: isProcess ? 2 : 6,// 设置选中边缘的宽度
  698. };
  699. // 保存当前选中的边缘作为上一个选中边缘
  700. previousEdge = seledge.value;
  701. }
  702. let dataflowshow=ref(false);
  703. let youhuaFFDtable = ref([
  704. { name:'FFD参数(sample)', steamflag:1 }
  705. ])
  706. let youhuaCSTtable = ref([
  707. { name:"上表面CST参数(upper)", steamflag:1 },
  708. { name:'下表面CST参数(lower)', steamflag:1 }
  709. ])
  710. let youhuaTACStable = ref([
  711. { name:'TACS参数', steamflag:1 }
  712. ])
  713. let steamtypeoptions = ref([
  714. { label:'约束条件', value:1 },
  715. { label:'优化目标', value:2 }
  716. ])
  717. let ADflowyouhuatable = ref([
  718. { code: "cl", name:'升力系数Cl', comtype:2 , steamflag:1, steamtype:1 },
  719. { code: "cd", name:'阻力系数Cd', comtype:2 , steamflag:1, steamtype:1 },
  720. { code: "cm", name:'力矩系数Cm', comtype:2 , steamflag:1, steamtype:1 },
  721. ])
  722. let ADflowMathfunctable = ref([])
  723. let TacsMathFunctable = ref([])
  724. let MathFuncyouhuatable = ref([])
  725. let Xfoilyouhuatable = ref([
  726. // { code:'', name:'升力系数Cl', comtype:2 , steamflag:1, steamtype:1 },
  727. // { code:'', name:'阻力系数Cd', comtype:2 , steamflag:1, steamtype:1 },
  728. // { code:'', name:'压阻力系数Cdp', comtype:2 , steamflag:1, steamtype:1 },
  729. // { code:'', name:'力矩系数Cm', comtype:2 , steamflag:1, steamtype:1 },
  730. // { code:'', name:'上表面转换点位置xtr-upper', comtype:2 , steamflag:1, steamtype:1 },
  731. // { code:'', name:'下表面转换点位置xtr-lower', comtype:2 , steamflag:1, steamtype:1 },
  732. ])
  733. let checkAll = ref(false);
  734. let isIndeterminate = ref(false);
  735. const dataTables = {
  736. '1': youhuaFFDtable,
  737. '2': youhuaCSTtable,
  738. '3': ADflowyouhuatable,
  739. '4': Xfoilyouhuatable,
  740. '5': ADflowMathfunctable,
  741. '6': TacsMathFunctable,
  742. '7': youhuaTACStable,
  743. '8': MathFuncyouhuatable,
  744. };
  745. const handlecheckFlagchange = () => {
  746. const table = dataTables[datacontent.value];
  747. if (!table) return;
  748. let checkedCount = table.value.filter(item => Boolean(item.steamflag)).length;
  749. checkAll.value = checkedCount === table.value.length;
  750. isIndeterminate.value = checkedCount > 0 && checkedCount < table.value.length;
  751. };
  752. const handlecheckAllchange = (val) => {
  753. const table = dataTables[datacontent.value];
  754. if (!table) return;
  755. table.value.forEach(item => item.steamflag = val ? 1 : 0);
  756. isIndeterminate.value = false;
  757. };
  758. // 双击线段弹窗确认
  759. const confirmselection=()=>{
  760. const table = dataTables[datacontent.value];
  761. let checkedData = table.value.filter((item) => item.steamflag).map((item) => item.name);
  762. console.log('xuanzhongshuju:',checkedData);
  763. console.log('seledge:',seledge.value);
  764. seledge.value.label=checkedData.join('\n');
  765. // 保存数据流
  766. dataFlowsave();
  767. dataflowshow.value = false;
  768. }
  769. const xfid = ref('')
  770. const adid = ref('')
  771. const mfcid = ref('')
  772. const tacsid = ref('')
  773. // 监听组件xfoil返回的xfid
  774. const handleXfid = (xfidFromB) => {
  775. xfid.value = xfidFromB.value;
  776. noid.value.data.xfid = xfid.value;
  777. };
  778. const handleAdid = (adidFromB) => {
  779. adid.value = adidFromB.value;
  780. noid.value.data.adid = adid.value;
  781. }
  782. const handleMfcid = (mfcidFromB) => {
  783. mfcid.value = mfcidFromB.value;
  784. noid.value.data.mfcid = mfcid.value;
  785. };
  786. const handleTacsid = (tacsidFromB) => {
  787. tacsid.value = tacsidFromB.value;
  788. noid.value.data.tacsid = tacsid.value;
  789. };
  790. let datacontent = ref('')
  791. // 判定是哪种线段
  792. function onEdgeDoubleClick(e) {
  793. console.log('Edge Double Click', e)
  794. if(e.edge.data.type==='process'){
  795. console.log('逻辑流不打开弹窗');
  796. return ;
  797. }
  798. seledge.value = e.edge;
  799. // dataflowshow.value = true
  800. console.log('qidian:',e.edge.sourceNode.data.name);
  801. console.log('zhongdian:',e.edge.targetNode.data.name);
  802. let qidian = e.edge.sourceNode.data.name;
  803. let zhongdian = e.edge.targetNode.data.name;
  804. let youhualist = ['optimizer','optimizer3','optimizer1','optimizer2'];
  805. if( youhualist.includes(qidian) && zhongdian ==='FFD' ){
  806. datacontent.value = '1';
  807. dataflowshow.value = true;
  808. }else if( youhualist.includes(qidian) && zhongdian ==='CST') {
  809. datacontent.value = '2';
  810. dataflowshow.value = true;
  811. }else if( qidian === 'ADflow' && youhualist.includes(zhongdian) ) {
  812. datacontent.value = '3';
  813. // emitter.emit('requestGetadid',pid.value);
  814. adid.value = e.edge.sourceNode.data.adid;
  815. // console.log('adid:',adid.value)
  816. if(adid.value) {
  817. querydataFlow(adid);
  818. dataflowshow.value = true;
  819. }else{
  820. ElMessage.error('ADflow未初始化!')
  821. }
  822. }else if ( qidian === 'Xfoil' && youhualist.includes(zhongdian) ) {
  823. datacontent.value = '4';
  824. // emitter.emit('requestGetxfid',pid.value);
  825. xfid.value = e.edge.sourceNode.data.xfid;
  826. // console.log('xfid:',xfid.value)
  827. if(xfid.value) {
  828. querydataFlow(xfid);
  829. dataflowshow.value = true;
  830. }else{
  831. ElMessage.error('Xfoil未初始化!')
  832. }
  833. }else if ( qidian === 'ADflow' && zhongdian ==='MathFunc' ) {
  834. datacontent.value = '5';
  835. adid.value = e.edge.sourceNode.data.adid;
  836. if(adid.value) {
  837. querydataFlow(adid);
  838. dataflowshow.value = true;
  839. }else{
  840. ElMessage.error('ADflow未初始化!')
  841. }
  842. }else if ( qidian === 'TACS' && zhongdian ==='MathFunc' ) {
  843. datacontent.value = '6';
  844. tacsid.value = e.edge.sourceNode.data.tacsid;
  845. if(tacsid.value) {
  846. querydataFlow(tacsid);
  847. dataflowshow.value = true;
  848. }else{
  849. ElMessage.error('TACS未初始化!')
  850. }
  851. }else if( youhualist.includes(qidian) && zhongdian ==='TACS') {
  852. datacontent.value = '7';
  853. dataflowshow.value = true;
  854. }else if( qidian ==='MathFunc' && youhualist.includes(zhongdian)) {
  855. datacontent.value = '8';
  856. mfcid.value = e.edge.sourceNode.data.mfcid;
  857. if(mfcid.value) {
  858. querydataFlow(mfcid);
  859. dataflowshow.value = true;
  860. }else{
  861. ElMessage.error('MathFunc未初始化!')
  862. }
  863. }
  864. console.log('leixing:',datacontent.value);
  865. nextTick(() => {
  866. handlecheckFlagchange();
  867. });
  868. }
  869. const querydataFlow = (comid) => {
  870. const params = {
  871. transCode: "MDO0052",
  872. pid: pid.value,
  873. comid: comid.value
  874. }
  875. request(params).then((res) => {
  876. if(datacontent.value === '3'){
  877. ADflowyouhuatable.value = res.params;
  878. handlecheckFlagchange();
  879. }
  880. if(datacontent.value === '4'){
  881. Xfoilyouhuatable.value = res.params;
  882. handlecheckFlagchange();
  883. }
  884. if(datacontent.value === '5'){
  885. ADflowMathfunctable.value = res.params;
  886. handlecheckFlagchange();
  887. }
  888. if(datacontent.value === '6'){
  889. TacsMathFunctable.value = res.params;
  890. handlecheckFlagchange();
  891. }
  892. if(datacontent.value === '8'){
  893. MathFuncyouhuatable.value = res.params;
  894. handlecheckFlagchange();
  895. }
  896. })
  897. .catch((err) => {
  898. ElMessage.error(err.returnMsg)
  899. })
  900. }
  901. const dataFlowsave = () => {
  902. let stringArray = '';
  903. if(datacontent.value === '3'){
  904. stringArray = convertToStringArray([],ADflowyouhuatable.value);
  905. }else if(datacontent.value === '4'){
  906. stringArray = convertToStringArray([],Xfoilyouhuatable.value);
  907. }else if(datacontent.value === '5'){
  908. stringArray = convertToStringArray([],ADflowMathfunctable.value);
  909. }else if(datacontent.value === '6'){
  910. stringArray = convertToStringArray([],TacsMathFunctable.value);
  911. }else if(datacontent.value === '8'){
  912. stringArray = convertToStringArray([],MathFuncyouhuatable.value);
  913. }else{
  914. return;
  915. }
  916. const params = {
  917. transCode: "MDO0053",
  918. paramstr: stringArray,
  919. };
  920. request(params).then((res) => {
  921. ElMessage({
  922. message: '数据流保存成功',
  923. type: 'success',
  924. })
  925. })
  926. .catch((err) => {
  927. ElMessage.error('数据流保存失败')
  928. })
  929. }
  930. const convertToStringArray = (result, Data) => {
  931. console.log('Data:', Data);
  932. // 安全检查 Data,确保它是一个数组
  933. if (!Array.isArray(Data)) {
  934. console.error('Data should be an array');
  935. return result; // 返回原 result 或者根据需要返回其他默认值
  936. }
  937. result = Data.map(row => {
  938. // 获取每一行的 `code`, `name`, `value` 和 `flag`
  939. const paramid = row.paramid ?? ' ';
  940. const steamflag = row.steamflag ?? '';
  941. const steamtype = row.steamtype ?? ' ';
  942. // 将字段连接为一个以逗号分隔的字符串
  943. return `${paramid},${steamflag},${steamtype}`;
  944. }).join(';'); // 每行之间用分号分隔
  945. return result;
  946. }
  947. // 右键更改名字
  948. // const onContextMenu = (e) => {
  949. // e.preventDefault(); // 阻止浏览器默认的右键菜单
  950. // const node = e.target.closest(".vue-flow__node");
  951. // console.log("nodes:",nodes);
  952. // console.log("node:",node);
  953. // if (node) {
  954. // // 获取当前右键点击的节点
  955. // const nodeId = node.getAttribute("data-id");
  956. // const clickedNode = nodes.value.find((n) => n.id === nodeId);
  957. // console.log("clickedNode:",clickedNode);
  958. // if (clickedNode) {
  959. // noid.value = clickedNode;
  960. // changeName.value.name = clickedNode.label; // 将当前节点的label放入弹窗中
  961. // changeNameshow.value = true; // 显示弹窗
  962. // }
  963. // }
  964. // };
  965. onInit((vueFlowInstance) => {
  966. vueFlowInstance.fitView()
  967. })
  968. onNodeDragStop(({ event, nodes, node }) => {
  969. console.log(nodes)
  970. Nested.value=nodes;
  971. console.log('Node Drag Stop', { event, nodes, node })
  972. })
  973. // onConnect((connection) => {
  974. // addEdges(connection)
  975. // console.log('Connection', connection)
  976. // })
  977. function updatePos() {
  978. nodes.value = nodes.value.map((node) => {
  979. return {
  980. ...node,
  981. position: {
  982. x: Math.random() * 400,
  983. y: Math.random() * 400,
  984. },
  985. }
  986. })
  987. }
  988. function removeEdge(id) {
  989. if(!seledge.value){
  990. return;
  991. }
  992. id = Edgeid.value;
  993. const wid = seledge.value.data.wid;
  994. vueFlowRef.value.removeEdges(id);
  995. deleteflow(wid);
  996. seledge.value=null;
  997. console.log('msg:',datatree.value);
  998. }
  999. // 触摸
  1000. const onDrop1=(event)=>{
  1001. // console.log('onDrop1:',event);
  1002. onDrop(event);
  1003. emitter.emit('doSomethingEvent');
  1004. }
  1005. function removeNode(id) {
  1006. id = noid.value.id;
  1007. const wid = noid.value.data.wid;
  1008. console.log('removeNodewid:',wid);
  1009. if(datatree.value==undefined){
  1010. if(nodes.value.length>0){
  1011. for (let i = 0; i <nodes.value.length; i++) {
  1012. if(id==nodes.value[i].id){
  1013. console.log(44444)
  1014. console.log( nodes.value[i]);
  1015. nodes.value.splice(i, 1)
  1016. deleteflow(wid);
  1017. }
  1018. }
  1019. console.log( nodes.value);
  1020. }
  1021. }else{
  1022. if(nodes.value.length>0){
  1023. for (let i = 0; i <nodes.value.length; i++) {
  1024. if(id==nodes.value[i].id){
  1025. console.log( nodes.value[i]);
  1026. nodes.value.splice(i, 1)
  1027. }
  1028. }
  1029. }
  1030. for (let i = 0; i <datatree.value[0].children.length; i++) {
  1031. if(id.includes(datatree.value[0].children[i].Text)){
  1032. for (let j = 0; j <datatree.value[0].children[i].children.length; j++) {
  1033. if(id==datatree.value[0].children[i].children[j].id){
  1034. //datatree.value[0].children.splice(datatree.value[0].children[i].children[j], 1);
  1035. datatree.value[0].children[i].children.splice(j, 1);
  1036. deleteflow(wid);
  1037. vueFlowRef.value.removeNodes(id);
  1038. removeRelatedEdges(id);
  1039. }
  1040. }
  1041. }
  1042. }
  1043. }
  1044. }
  1045. function removeRelatedEdges(nodeId) {
  1046. //过滤出与该节点相关的连线
  1047. const relatedEdges = edges.value.filter(
  1048. (edge) => edge.source === nodeId || edge.target === nodeId
  1049. );
  1050. // 遍历删除关联的连线
  1051. relatedEdges.forEach((edge) => {
  1052. if (edge.data && edge.data.wid) {
  1053. deleteflow(edge.data.wid);
  1054. }
  1055. });
  1056. }
  1057. // 删除提示
  1058. const confirmDelete = () => {
  1059. ElMessageBox.confirm(
  1060. '确定要删除全部吗?删除后不可恢复!',
  1061. '删除确认',
  1062. {
  1063. confirmButtonText: '确定',
  1064. cancelButtonText: '取消',
  1065. type: 'warning',
  1066. }
  1067. )
  1068. .then(() => {
  1069. removeall();
  1070. })
  1071. .catch(() => {
  1072. ElMessage({
  1073. type: 'info',
  1074. message: '已取消删除',
  1075. })
  1076. })
  1077. }
  1078. function removeall() {
  1079. try {
  1080. const allnodes = nodes.value;
  1081. const allEdges = edges.value;
  1082. for (let i = 0; i < allnodes.length; i++) {
  1083. if (allnodes[i].data.wid) {
  1084. deleteflow(allnodes[i].data.wid);
  1085. }
  1086. }
  1087. for (let i = 0; i < allEdges.length; i++) {
  1088. if (allEdges[i].data.wid) {
  1089. deleteflow(allEdges[i].data.wid);
  1090. }
  1091. }
  1092. nodes.value = []
  1093. edges.value = []
  1094. Nested2.value = []
  1095. Nested.value = []
  1096. // 判断 datatree 是否为空或未定义
  1097. if (!datatree.value || datatree.value.length === 0 || !datatree.value[0]?.children) {
  1098. console.warn('datatree 数据为空或未定义')
  1099. ElMessage({
  1100. type: 'warning',
  1101. message: '没有数据可以删除'
  1102. })
  1103. return
  1104. }
  1105. // 清空 datatree 的 children
  1106. for (let i = 0; i < datatree.value[0].children.length; i++) {
  1107. if (datatree.value[0]?.children[i]?.children) {
  1108. datatree.value[0].children[i].children = []
  1109. }
  1110. }
  1111. } catch (error) {
  1112. console.error('删除失败:', error)
  1113. ElMessage({
  1114. type: 'error',
  1115. message: '删除过程中出错'
  1116. })
  1117. }
  1118. }
  1119. // 流查询
  1120. const queryflow = () => {
  1121. const params = {
  1122. transCode: 'MDO0057',
  1123. pid: pid.value,
  1124. }
  1125. request(params)
  1126. .then((res) => {
  1127. console.log(res);
  1128. })
  1129. .catch((err) => {
  1130. ElMessage.error(err.returnMsg)
  1131. })
  1132. }
  1133. // 保存流
  1134. const saveflow = async (pid,wid, uid, type, fromuid, touid) => {
  1135. const params = {
  1136. transCode: 'MDO0058',
  1137. pid: pid || '',
  1138. wid: wid || '', // 流ID
  1139. uid: uid || '',
  1140. type: type || '',
  1141. fromuid: fromuid || '',
  1142. touid: touid || '',
  1143. };
  1144. try {
  1145. // 直接使用 await 等待 request 返回
  1146. const res = await request(params);
  1147. return res.wid; // 返回 wid
  1148. } catch (err) {
  1149. // 处理错误
  1150. ElMessage.error(err.returnMsg || '保存流程失败');
  1151. }
  1152. };
  1153. // async function saveFlowExample() {
  1154. // try {
  1155. // const wid = await saveflow('flow123', 'user001', 'process', 'fromA', 'toB');
  1156. // console.log('返回的 wid:', wid);
  1157. // } catch (err) {
  1158. // console.error('保存流程失败:', err.message);
  1159. // }
  1160. // }
  1161. // saveFlowExample();
  1162. // 删除流
  1163. const deleteflow = (nowid) => {
  1164. const params = {
  1165. transCode: 'MDO0059',
  1166. wid: nowid,
  1167. }
  1168. request(params)
  1169. .then((res) => {
  1170. console.log(res);
  1171. })
  1172. .catch((err) => {
  1173. ElMessage.error('删除流程失败')
  1174. })
  1175. }
  1176. async function logToObject1() {
  1177. let obj = { nodes: toObject().nodes,edges:toObject().edges };
  1178. mergedObj.value=JSON.stringify(obj);
  1179. try {
  1180. const container = vueFlowRef.value.$el;
  1181. const canvas = await html2canvas(container);
  1182. const img = canvas.toDataURL('image/png');
  1183. // 创建一个图片元素并设置src属性为转换后的图片数据
  1184. vueflowimg.value=img
  1185. if(vueflowimg.value!=''){
  1186. console.log("进入了")
  1187. addflow();
  1188. }
  1189. // 添加到DOM中或者做其他操作
  1190. } catch (error) {
  1191. console.error('转换出错:', error);
  1192. }
  1193. }
  1194. //添加接口
  1195. const addflow = () => {
  1196. const savedObj = JSON.parse(sessionStorage.getItem("objlist"));
  1197. const stypeValue = savedObj ? savedObj.stype : '';
  1198. // 用于首页主界面切换数据一致
  1199. const updateobjlist = {
  1200. pid: pid.value,
  1201. name: newobj.value.name,
  1202. remark: newobj.value.description,
  1203. image: vueflowimg.value,
  1204. isshare: '1',
  1205. flow: mergedObj.value,
  1206. stype: stypeValue,
  1207. }
  1208. sessionStorage.setItem("objlist",JSON.stringify(updateobjlist));
  1209. console.log("打印stypeValue:",stypeValue);
  1210. const params = {
  1211. transCode: 'MDO0002',
  1212. pid: pid.value,
  1213. name: newobj.value.name,
  1214. remark:newobj.value.description,
  1215. image:vueflowimg.value,
  1216. isshare:'1',
  1217. flow:mergedObj.value ,
  1218. stype:stypeValue,
  1219. }
  1220. console.log(params);
  1221. request(params)
  1222. .then((res) => {
  1223. console.log(res);
  1224. ElMessage({
  1225. message: '工程保存成功',
  1226. type: 'success',
  1227. })
  1228. })
  1229. .catch((err) => {
  1230. ElMessage.error(err.returnMsg)
  1231. })
  1232. }
  1233. /**
  1234. * Resets the current viewport transformation (zoom & pan)
  1235. */
  1236. function resetTransform() {
  1237. setViewport({ x: 0, y: 0, zoom: 1 })
  1238. }
  1239. function toggleDarkMode() {
  1240. dark.value = !dark.value;
  1241. if(dark.value){
  1242. iconcolor.value='#fff'
  1243. }else{
  1244. iconcolor.value='#000'
  1245. }
  1246. }
  1247. // 禁用右键菜单的函数
  1248. const onNodeContextMenu1 = (event) => {
  1249. event.preventDefault();
  1250. };
  1251. onMounted(() => {
  1252. setTimeout(function() {
  1253. getroter();
  1254. }, 1500);
  1255. // childfun();
  1256. // 点击其他区域取消线段选中
  1257. if (vueFlowRef.value) {
  1258. vueFlowRef.value.$el.addEventListener('click', (event) => {
  1259. // 确保点击的不是边缘
  1260. if (seledge.value && !event.target.closest('.vue-flow__edge')) {
  1261. cleanEdgeselect();
  1262. }
  1263. });
  1264. }
  1265. document.addEventListener('contextmenu', onNodeContextMenu1);
  1266. emitter.on("xfidFromxfoil", handleXfid);
  1267. emitter.on("adidFromadflow", handleAdid);
  1268. emitter.on("mfcidFromMathFunc", handleMfcid);
  1269. emitter.on("tacsidFromTACS", handleTacsid);
  1270. });
  1271. const cleanEdgeselect = () => {
  1272. if(seledge.value) {
  1273. // 恢复选中边缘的原始样式
  1274. seledge.value.style = {
  1275. ...seledge.value.style,
  1276. stroke: seledge.value.originalColor,
  1277. strokeWidth: previousEdge?.originalWidth || 1, // 恢复原始宽度
  1278. };
  1279. // 清空选中的边缘
  1280. seledge.value = null;
  1281. Edgeid.value = null;
  1282. previousEdge = null;
  1283. }
  1284. }
  1285. // 在组件销毁前移除右键菜单禁用
  1286. onBeforeUnmount(() => {
  1287. document.removeEventListener('contextmenu', onNodeContextMenu1);
  1288. });
  1289. onUnmounted(() => {
  1290. emitter.off('child2Data');
  1291. emitter.off("xfidFromxfoil", handleXfid);
  1292. emitter.off("adidFromadflow", handleAdid);
  1293. emitter.off("mfcidFromMathFunc", handleMfcid);
  1294. emitter.off("tacsidFromTACS", handleTacsid);
  1295. });
  1296. // 获取链接
  1297. const getroter=()=>{
  1298. //datatree.value[0].children=[];
  1299. let objlist=JSON.parse(sessionStorage.getItem("objlist"));
  1300. if(objlist.flow!=''){
  1301. let nodesflow=JSON.parse(objlist.flow)
  1302. nodes.value=nodesflow.nodes;
  1303. edges.value=nodesflow.edges;
  1304. }
  1305. newobj.value.name=objlist.name;
  1306. newobj.value.description=objlist.remark;
  1307. pid.value=objlist.pid;
  1308. // let item={
  1309. // id:'1-0',
  1310. // label: objlist.name,
  1311. // img:r2,
  1312. // }
  1313. // console.log( datatree.value[0].children);
  1314. // datatree.value[0].children.push(item);
  1315. }
  1316. //改变线的类型
  1317. const linestrokeWidth=(type)=>{
  1318. if(type=='process'){
  1319. linenum.value=1;
  1320. linecolor.value = '#2267B1';
  1321. lineType.value = 'process';
  1322. }else if(type=='data'){
  1323. linenum.value=6;
  1324. linecolor.value = "rgba(150, 150, 150, 0.2)";
  1325. lineType.value = 'data';
  1326. }
  1327. }
  1328. //改变线的颜色
  1329. const changeAllEdgesColor = (color1) => {
  1330. console.log('yanse:', color1);
  1331. linecolor.value = color1;
  1332. // 找到当前选中的边缘
  1333. if (seledge.value) {
  1334. // 更新该边缘的颜色
  1335. let newColor = linecolor.value;
  1336. // 如果选中的线 `linetype` 是 `data`,则增加透明度 0.2
  1337. if (seledge.value.data.type === 'data') {
  1338. newColor = convertToRGBA(linecolor.value, 0.2);
  1339. }
  1340. const updatedEdge = {
  1341. ...seledge.value,
  1342. style: {
  1343. ...seledge.value.style,
  1344. stroke: newColor, // 只修改颜色
  1345. }
  1346. };
  1347. // 更新 edges 数组
  1348. const updatedEdges = edges.value.map(edge =>
  1349. edge.id === seledge.value.id ? updatedEdge : edge
  1350. );
  1351. edges.value = updatedEdges; // 持久化修改后的边缘
  1352. }
  1353. };
  1354. // 颜色转换函数:将 Hex / RGB 转换为 RGBA
  1355. const convertToRGBA = (color, alpha) => {
  1356. if (color.startsWith('#')) {
  1357. // 处理 Hex 颜色(例如 #ff0000 转换为 rgba(255, 0, 0, 0.3))
  1358. const r = parseInt(color.substring(1, 3), 16);
  1359. const g = parseInt(color.substring(3, 5), 16);
  1360. const b = parseInt(color.substring(5, 7), 16);
  1361. return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  1362. } else if (color.startsWith('rgb')) {
  1363. // 处理 RGB 颜色,替换透明度
  1364. return color.replace(/rgb(a?)\(([^)]+)\)/, `rgba($2, ${alpha})`);
  1365. }
  1366. return color; // 默认返回原始颜色(避免报错)
  1367. };
  1368. watch(() => seledge.value, (newItems, oldItems) => {
  1369. if(seledge.value!=null){
  1370. // seledge.value.style.stroke = linecolor.value;
  1371. }
  1372. });
  1373. defineExpose({changeAllEdgesColor,linestrokeWidth,getroter,onSelection,bgcolorfunc,logToObject1});
  1374. </script>
  1375. <style>
  1376. /* .vue-flow__edge.selected .vue-flow__edge-path, .vue-flow__edge:focus .vue-flow__edge-path, .vue-flow__edge:focus-visible .vue-flow__edge-path {
  1377. stroke: #555 !important;
  1378. } */
  1379. .vue-flow__edge:focus .vue-flow__edge-path, .vue-flow__edge:focus-visible .vue-flow__edge-path {
  1380. stroke: #555 !important;
  1381. }
  1382. .vue-flow__edge {
  1383. text-align: left;
  1384. /* 设置edges的左对齐 */
  1385. }
  1386. .vue-flow__edge-text {
  1387. transform: translateY(-10px); /* 将 label 向上偏移 */
  1388. background: transparent !important;
  1389. font-size: 8px;
  1390. font-family: 'Microsoft YaHei';
  1391. color: #333333;
  1392. }
  1393. .vue-flow__edge-textbg {
  1394. fill: transparent !important; /* 将背景设置为透明 */
  1395. }
  1396. #contextMenu {
  1397. display: none;
  1398. position: absolute;
  1399. background-color: #fff;
  1400. border-radius: 5px;
  1401. padding: 10px;
  1402. text-align: center;
  1403. color: black;
  1404. font-size: 14px;
  1405. font-weight: 400;
  1406. cursor: pointer;
  1407. z-index: 99999;
  1408. }
  1409. .vue-flow__node-default.selectable:hover,
  1410. .vue-flow__node-input.selectable:hover,
  1411. .vue-flow__node-output.selectable:hover {
  1412. box-shadow: none;
  1413. }
  1414. panel {
  1415. cursor: pointer;
  1416. position: absolute;
  1417. z-index: 100000;
  1418. }
  1419. .remove {
  1420. background: #fff;
  1421. color: #666;
  1422. margin: 0 10px;
  1423. font-size: 12px;
  1424. }
  1425. .vue-flow__node-default, .vue-flow__node-input, .vue-flow__node-output{
  1426. /* width: auto !important; */
  1427. border: none;
  1428. background-color: rgba(0,0,0,0);
  1429. }
  1430. .node-content {
  1431. cursor: move; /* 更改鼠标光标表示可拖动 */
  1432. }
  1433. .vue-flow__node {
  1434. cursor: move;
  1435. }
  1436. /* 禁用文本选中效果 */
  1437. .left_main * {
  1438. -webkit-user-select: none; /* Safari */
  1439. -moz-user-select: none; /* Firefox */
  1440. -ms-user-select: none; /* IE10+/Edge */
  1441. user-select: none; /* Standard syntax */
  1442. }
  1443. .lableaniu{
  1444. font-size: 12px;
  1445. background-color: #ddd;
  1446. padding: 4px 16px;
  1447. /* margin-top: -17px; */
  1448. margin-left: 5px;
  1449. margin-top: 0px;
  1450. border-radius: 1px;
  1451. }
  1452. .vue-flow__controls-button svg{
  1453. max-width: 16px;
  1454. max-height: 16px;
  1455. }
  1456. .field{
  1457. display: flex;
  1458. }
  1459. </style>