index.vue 55 KB

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