ADflow.vue 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019
  1. <template>
  2. <div class="XFpdding" style="height: 400px">
  3. <ul>
  4. <li
  5. class="item"
  6. v-for="(tab, index) in tabslist1"
  7. :key="index"
  8. :class="{ active: currentTab1 === index }"
  9. @click="selectTab1(index)"
  10. >
  11. <img :src="tab.imgSrc" style="width: 22px;"/>
  12. {{ tab.name }}
  13. </li>
  14. </ul>
  15. <!-- 网格文件 -->
  16. <!-- 执行 -->
  17. <div
  18. class="eldesign classtable"
  19. style="margin-top: 10px;"
  20. v-show="currentTab1 == '0'"
  21. >
  22. <div style="display: flex;flex-direction: column;">
  23. <el-form-item label="网格文件:" :label-width="formLabelWidth3" style="width: 100%">
  24. <el-row style="width: 100%">
  25. <el-col :span="23">
  26. <el-input
  27. v-model="adflowvalue.gridfile"
  28. readonly
  29. :step="100"
  30. :min="0"
  31. :max="1000"
  32. controls-position="right"
  33. />
  34. </el-col>
  35. <!-- 文件上传按钮部分 -->
  36. <el-col :span="1" style="display: flex; align-items: center; margin-left: -35px">
  37. <fileUploads
  38. :projectId="124"
  39. solverType="exampleSolver"
  40. accept=".cgns"
  41. upId="adflow"
  42. name="点击选择文件"
  43. :imgSrc="meshFileImgSrc"
  44. @upload-success="handleFileUploadSuccess"
  45. @update-fileName="updateFileName"
  46. @update-percentage="updatePercentage"
  47. @upload-status="getUploadStatus"
  48. />
  49. </el-col>
  50. </el-row>
  51. <!-- 进度条 -->
  52. <el-row v-if="showProgress" style="width: 100%; margin-top: 10px;">
  53. <el-col :span="20">
  54. <el-progress :percentage="percentage"></el-progress>
  55. </el-col>
  56. <el-col :span="4">
  57. <div style="line-height: 15px">{{uploadStatus}}</div>
  58. </el-col>
  59. <!-- <el-col :span="2">
  60. <el-button type="text" @click="fileDel" :icon="Delete" circle style="color: red; padding-bottom:25px;" />
  61. </el-col> -->
  62. </el-row>
  63. </el-form-item>
  64. <div
  65. style="flex-grow: 1; height:300px"
  66. v-loading="isLoading"
  67. element-loading-text="拼命加载中...">
  68. <cloudChart :data="cgnsData" :height=canvasHeight />
  69. </div>
  70. </div>
  71. </div>
  72. <!-- 来流参数 v-show="currentTab=='0'"-->
  73. <div v-show="currentTab1 == '1'">
  74. <div class="eldesign classtable" style="margin-top: 10px">
  75. <el-table :data="inParams" border style="width: 100%; " :header-cell-class-name="headerCellClassName">
  76. <el-table-column type="index" width="70" label="编号" />
  77. <el-table-column prop="name" label="参数名称">
  78. <!-- <template #default="{ row }">
  79. <el-input v-model="row.name" @change="handleEdit(row)" />
  80. </template> -->
  81. </el-table-column>
  82. <el-table-column prop="value" label="参数值">
  83. <template #default="{ row }">
  84. <el-input v-model="row.value" type="number" />
  85. </template>
  86. </el-table-column>
  87. <el-table-column prop="flag" label="启用" width="100">
  88. <template v-slot="scope">
  89. <el-checkbox
  90. :false-label="0"
  91. :true-label="1"
  92. :label="false"
  93. v-model="scope.row.flag"
  94. />
  95. </template>
  96. </el-table-column>
  97. </el-table>
  98. </div>
  99. </div>
  100. <!-- 设置参数 -->
  101. <div
  102. class="eldesign classtable"
  103. style="margin-top: 10px; height: 340px;overflow: auto;"
  104. v-show="currentTab1 == '2'"
  105. >
  106. <el-form-item label="分析对象:" :label-width="formLabelWidth1">
  107. <el-select
  108. v-model="adflowvalue.proname"
  109. :suffix-icon="CaretBottom"
  110. placeholder="请选择"
  111. >
  112. <el-option
  113. v-for="item in objlist"
  114. :key="item.value"
  115. :label="item.label"
  116. :value="item.value"
  117. >
  118. </el-option>
  119. </el-select>
  120. </el-form-item>
  121. <el-form-item label="计算进程数:" :label-width="formLabelWidth1">
  122. <el-input
  123. v-model="adflowvalue.countp"
  124. />
  125. </el-form-item>
  126. <el-form-item label="Newton-Krylov求解:" :label-width="formLabelWidth1">
  127. <el-radio-group v-model="adflowvalue.NewtonKrylov">
  128. <el-radio :value="1" :label="1">是</el-radio>
  129. <el-radio :value="0" :label="0">否</el-radio>
  130. </el-radio-group>
  131. </el-form-item>
  132. <el-form-item label="ANK求解:" :label-width="formLabelWidth1">
  133. <el-radio-group v-model="adflowvalue.ANK">
  134. <el-radio :value="1" :label="1">是</el-radio>
  135. <el-radio :value="0" :label="0">否</el-radio>
  136. </el-radio-group>
  137. </el-form-item>
  138. <!-- <el-form-item label="工况条件:" :label-width="formLabelWidth1">
  139. <el-select
  140. v-model="adflowvalue.proname"
  141. :suffix-icon="CaretBottom"
  142. placeholder="请选择"
  143. >
  144. <el-option
  145. v-for="item in wclist"
  146. :key="item.value"
  147. :label="item.label"
  148. :value="item.value"
  149. >
  150. </el-option>
  151. </el-select>
  152. </el-form-item> -->
  153. <el-form-item label="计算维数:" :label-width="formLabelWidth1">
  154. <el-select
  155. v-model="isairfoil"
  156. :suffix-icon="CaretBottom"
  157. placeholder="请选择"
  158. @change="isairfoilChange"
  159. >
  160. <el-option
  161. v-for="item in isairfoilList"
  162. :key="item.value"
  163. :label="item.label"
  164. :value="item.value"
  165. >
  166. </el-option>
  167. </el-select>
  168. </el-form-item>
  169. <el-form-item label="控制方程:" :label-width="formLabelWidth1">
  170. <el-select
  171. v-model="equationtype"
  172. :suffix-icon="CaretBottom"
  173. placeholder="请选择"
  174. >
  175. <el-option
  176. v-for="item in equationtypelist"
  177. :key="item.value"
  178. :label="item.label"
  179. :value="item.value"
  180. >
  181. </el-option>
  182. </el-select>
  183. </el-form-item>
  184. <el-form-item label="升力定义方向:" :label-width="formLabelWidth1">
  185. <el-select
  186. v-model="liftindex"
  187. :suffix-icon="CaretBottom"
  188. placeholder="请选择"
  189. >
  190. <el-option
  191. v-for="item in liftindexlist"
  192. :key="item.value"
  193. :label="item.label"
  194. :value="item.value"
  195. >
  196. </el-option>
  197. </el-select>
  198. </el-form-item>
  199. <el-form-item label="特征长度(m):" :label-width="formLabelWidth1">
  200. <el-input
  201. v-model="adflowvalue.length"
  202. :step="100"
  203. :min="0"
  204. :max="1000"
  205. controls-position="right"
  206. />
  207. </el-form-item>
  208. <el-form-item label="参考温度(K):" :label-width="formLabelWidth1">
  209. <el-input
  210. v-model="adflowvalue.temperature"
  211. :step="1"
  212. :min="0"
  213. :max="1000"
  214. controls-position="right"
  215. />
  216. </el-form-item>
  217. <el-form-item label="参考面积(m²):" :label-width="formLabelWidth1">
  218. <el-input
  219. v-model="adflowvalue.area"
  220. :step="100"
  221. :min="0"
  222. :max="1000"
  223. controls-position="right"
  224. />
  225. </el-form-item>
  226. <el-form-item label="力矩中心(m):" :label-width="formLabelWidth1">
  227. <div style="display: flex">
  228. <el-input
  229. style="margin-right: 10px"
  230. v-model="adflowvalue.momx"
  231. :step="100"
  232. :min="0"
  233. :max="1000"
  234. controls-position="right"
  235. />
  236. <el-input
  237. style="margin-right: 10px"
  238. v-model="adflowvalue.momy"
  239. :step="100"
  240. :min="0"
  241. :max="1000"
  242. controls-position="right"
  243. />
  244. <el-input
  245. v-model="adflowvalue.momz"
  246. :step="100"
  247. :min="0"
  248. :max="1000"
  249. controls-position="right"
  250. />
  251. </div>
  252. </el-form-item>
  253. <el-form-item label="多重网格:" :label-width="formLabelWidth1">
  254. <el-input
  255. v-model="adflowvalue.mgcycle"
  256. :step="100"
  257. :min="0"
  258. :max="1000"
  259. controls-position="right"
  260. />
  261. </el-form-item>
  262. <el-form-item label="计算步数:" :label-width="formLabelWidth1">
  263. <el-input
  264. v-model="adflowvalue.ncycles"
  265. :step="100"
  266. :min="0"
  267. :max="1000"
  268. controls-position="right"
  269. />
  270. </el-form-item>
  271. <el-form-item label="监控变量:" :label-width="formLabelWidth1">
  272. <el-row>
  273. <el-col :span="12">
  274. <el-checkbox v-model="cl" :false-label="0"
  275. :true-label="1" label="升力系数Cl" style="height: 32px;" />
  276. <el-checkbox v-model="resrho" :false-label="0"
  277. :true-label="1" label="密度残差Resrho" style="height: 32px;" />
  278. </el-col>
  279. <el-col :span="12">
  280. <el-checkbox v-model="cd" :false-label="0"
  281. :true-label="1" label="阻力系数Cd" style="height: 32px;" />
  282. <el-checkbox v-model="cmz" :false-label="0"
  283. :true-label="1" label="力矩系数Cm" style="height: 32px;" />
  284. </el-col>
  285. </el-row>
  286. </el-form-item>
  287. <el-form-item label="细网格收敛残差:" :label-width="formLabelWidth1">
  288. <el-input
  289. v-model="adflowvalue.l2convergence"
  290. :step="100"
  291. :min="0"
  292. :max="1000"
  293. controls-position="right"
  294. />
  295. </el-form-item>
  296. <el-form-item label="粗网格收敛残差:" :label-width="formLabelWidth1">
  297. <el-input
  298. v-model="adflowvalue.l2convergencecoarse"
  299. :step="100"
  300. :min="0"
  301. :max="1000"
  302. controls-position="right"
  303. />
  304. </el-form-item>
  305. <el-form-item label="输出物面信息:" :label-width="formLabelWidth1">
  306. <el-radio-group v-model="writetecplotsurfacesolution">
  307. <el-radio :value="1" :label="1">是</el-radio>
  308. <el-radio :value="0" :label="0">否</el-radio>
  309. </el-radio-group>
  310. </el-form-item>
  311. <el-form-item label="输出切面信息:" :label-width="formLabelWidth1">
  312. <el-radio-group v-model="writeslicesolution" @change="writeslicesolutionChange">
  313. <el-radio :value="1" :label="1">是</el-radio>
  314. <el-radio :value="0" :label="0">否</el-radio>
  315. </el-radio-group>
  316. </el-form-item>
  317. <el-form-item v-show="qiemiansetshow" label="切面法相方向:" :label-width="formLabelWidth1">
  318. <el-select
  319. v-model="spandirection"
  320. :suffix-icon="CaretBottom"
  321. placeholder="请选择"
  322. >
  323. <el-option
  324. v-for="item in spandirectionindexlist"
  325. :key="item.value"
  326. :label="item.label"
  327. :value="item.value"
  328. >
  329. </el-option>
  330. </el-select>
  331. </el-form-item>
  332. <el-form-item v-show="qiemiansetshow" label="切面展向位置:" :label-width="formLabelWidth1">
  333. <el-input
  334. v-model="slices"
  335. :step="100"
  336. :min="0"
  337. :max="1000"
  338. controls-position="right"
  339. placeholder="多个位置以逗号分隔"
  340. />
  341. </el-form-item>
  342. </div>
  343. <!-- 分析参数 v-show="currentTab=='0'"-->
  344. <div v-show="currentTab1 == '3'">
  345. <div class="eldesign classtable" style="margin-top: 10px">
  346. <el-table :data="outParams" border style="width: 100%; " :header-cell-class-name="headerCellClassName">
  347. <el-table-column type="index" width="70" label="编号" />
  348. <el-table-column prop="name" label="参数名称" >
  349. </el-table-column>
  350. <el-table-column prop="value" label="参数值">
  351. <template #default="{ row }">
  352. <el-input v-model="row.value" type="number" />
  353. </template>
  354. </el-table-column>
  355. <el-table-column prop="flag" label="启用" width="100">
  356. <template v-slot="scope">
  357. <el-checkbox
  358. :false-label="0"
  359. :true-label="1"
  360. :label="false"
  361. v-model="scope.row.flag"
  362. />
  363. </template>
  364. </el-table-column>
  365. </el-table>
  366. </div>
  367. </div>
  368. </div>
  369. </template>
  370. <script setup>
  371. import { ref, onMounted, reactive, provide, nextTick } from "vue"
  372. import { ElMessage, ElButton, ElDialog, ElSelect } from "element-plus"
  373. import { Edit, CaretBottom, Delete } from "@element-plus/icons-vue"
  374. import { request, uploadFile } from "@/utils/request"
  375. import emitter from "@/utils/emitter"
  376. import fileUploads from "../components/fileuploads.vue";
  377. import meshFile from "@/assets/img/meshFile.png";
  378. import inputParams from "@/assets/img/inputParams.png";
  379. import configParams from "@/assets/img/configParams.png";
  380. import analysisParams from "@/assets/img/analysisParams.png";
  381. import { da } from "element-plus/es/locale/index.mjs";
  382. import cloudChart from "../threejsView/index.vue" // 云图
  383. const meshFileImgSrc = new URL("@/assets/img/open.png", import.meta.url).href;
  384. let canvasHeight = ref("300px")
  385. let isLoading = ref(false); // 控制 loading 状态
  386. let cgnsData = ref()
  387. let meshFileName = ref('');
  388. let percentage = ref(0);
  389. let uploadStatus = ref('');
  390. let isUploadSuccess = ref(true);
  391. let formLabelWidth3 = ref(120)
  392. let formLabelWidth1 = ref(180)
  393. let formLabelWidth200 = ref(200)
  394. let currentTab1 = ref(0)
  395. let pid = ref()
  396. let wid = ref()
  397. let adid = ref()
  398. let resrho = ref(1)
  399. let cl = ref(1)
  400. let cd = ref(1)
  401. let cmz = ref(1)
  402. let writetecplotsurfacesolution = ref(1)
  403. let spandirection = ref('x')
  404. let slices = ref("")
  405. let writeslicesolution = ref(1)
  406. let equationtype = ref("RANS")
  407. let equationtypelist = ref([
  408. { label: "RANS", value: "RANS" },
  409. { label: "Euler", value: "Euler" }
  410. ])
  411. let isairfoil = ref(1)
  412. let isairfoilList = ref([
  413. { label: "二维", value: 1 },
  414. { label: "三维", value: 0 }
  415. ])
  416. let liftindex = ref(1)
  417. let liftindexlist = ref([
  418. { label: "x", value: 1 },
  419. { label: "y", value: 2 },
  420. { label: "z", value: 3 }
  421. ])
  422. let spandirectionindexlist = ref([
  423. { label: "x", value: 'x' },
  424. { label: "y", value: 'y' },
  425. { label: "z", value: 'z' }
  426. ])
  427. let inParams = ref([
  428. {
  429. code: "mach",
  430. value: 0.734,
  431. name: "马赫数Ma",
  432. type: 1,
  433. flag: 1
  434. },
  435. {
  436. code: "reynolds",
  437. value: 6.5e6,
  438. name: "雷诺数Re",
  439. type: 1,
  440. flag: 1
  441. },
  442. {
  443. code: "alpha",
  444. value: 2.66482,
  445. name: "攻角AoA",
  446. type: 1,
  447. flag: 1
  448. },
  449. ])
  450. let outParams = ref([
  451. {
  452. code: "cl",
  453. value: "0.0",
  454. name: "升力系数Cl",
  455. type: 2,
  456. flag: 1
  457. },
  458. {
  459. code: "cd",
  460. value: "0.0",
  461. name: "阻力系数Cd",
  462. type: 2,
  463. flag: 1
  464. },
  465. {
  466. code: "cmz",
  467. value: "0.0",
  468. name: "力矩系数CmZ",
  469. type: 2,
  470. flag: 1
  471. },
  472. {
  473. code: " ",
  474. value: "0.0",
  475. name: "体积",
  476. type: 2,
  477. flag: 1
  478. }
  479. ])
  480. let outParams1 = ref([
  481. {
  482. code: "cl",
  483. value: "0.0",
  484. name: "升力系数Cl",
  485. type: 2,
  486. flag: 1
  487. },
  488. {
  489. code: "cd",
  490. value: "0.0",
  491. name: "阻力系数Cd",
  492. type: 2,
  493. flag: 1
  494. },
  495. {
  496. code: "cmz",
  497. value: "0.0",
  498. name: "力矩系数CmZ",
  499. type: 2,
  500. flag: 1
  501. },
  502. {
  503. code: " ",
  504. value: "0.0",
  505. name: "体积",
  506. type: 2,
  507. flag: 1
  508. }
  509. ])
  510. let outParams2 = ref([
  511. {
  512. code: "cl",
  513. value: "0.0",
  514. name: "升力系数Cl",
  515. type: 2,
  516. flag: 1
  517. },
  518. {
  519. code: "cd",
  520. value: "0.0",
  521. name: "阻力系数Cd",
  522. type: 2,
  523. flag: 1
  524. },
  525. {
  526. code: "cmx",
  527. value: "0.0",
  528. name: "力矩系数CmX",
  529. type: 2,
  530. flag: 1
  531. },
  532. {
  533. code: "cmy",
  534. value: "0.0",
  535. name: "力矩系数CmY",
  536. type: 2,
  537. flag: 1
  538. },
  539. {
  540. code: "cmz",
  541. value: "0.0",
  542. name: "力矩系数CmZ",
  543. type: 2,
  544. flag: 1
  545. },
  546. {
  547. code: " ",
  548. value: "0.0",
  549. name: "体积",
  550. type: 2,
  551. flag: 1
  552. }
  553. ])
  554. let adflowvalue = ref({
  555. gridfile: "",
  556. fid:'',
  557. countp:'1',
  558. NewtonKrylov:1,
  559. ANK:1,
  560. proname: "CRM",
  561. temperature: '288.15',
  562. length: 1,
  563. area: 1,
  564. momx: 0.25,
  565. momy: 0,
  566. momz: 0,
  567. mgcycle: "sg",
  568. ncycles: 500,
  569. l2convergence: 1.0e-5,
  570. l2convergencecoarse: 1.0e-4,
  571. })
  572. let objlist = ref([
  573. {label:'CRM' , value:'CRM'},
  574. ])
  575. let wclist = ref([{ label: "巡航工况", value: "cruise" }])
  576. let tabslist1 = ref([
  577. { id: "0", name: "网格文件", imgSrc: meshFile },
  578. { id: "1", name: "来流参数", imgSrc: inputParams },
  579. { id: "2", name: "设置参数", imgSrc: configParams },
  580. { id: "3", name: "分析参数", imgSrc: analysisParams }
  581. ])
  582. let websock = shallowRef(null);
  583. let times = ref({
  584. lockReconnect: false, //是否真正建立连接
  585. timeout: 60 * 1000, //30秒一次心跳
  586. heartBeatInterval: 30 * 1000, // 添加心跳发送间隔(30秒发一次)
  587. timeoutObj: null, //心跳倒计时
  588. serverTimeoutObj: null, //
  589. timeoutnum: null, //断开重连倒计时
  590. })
  591. const selectTab1 = (index) => {
  592. currentTab1.value = index
  593. }
  594. const headerCellClassName = ({ column }) => {
  595. // console.log('列:',column.property)
  596. if (column.property === 'name') {
  597. console.log('yanse',column.property)
  598. return 'header-blue';
  599. } else if (column.property === 'value') {
  600. return 'header-green';
  601. } else if (column.property === 'flag') {
  602. return 'header-yellow';
  603. }
  604. return '';
  605. };
  606. let qiemiansetshow = ref(true)
  607. const writeslicesolutionChange = (value) => {
  608. if (value === 1) {
  609. qiemiansetshow.value = true
  610. } else {
  611. qiemiansetshow.value = false
  612. }
  613. }
  614. const isairfoilChange = (value) => {
  615. if (value === 1) {
  616. outParams.value = outParams1.value
  617. } else {
  618. outParams.value = outParams2.value
  619. }
  620. }
  621. const convertToStringArray = (result, Data) => {
  622. console.log("Data:", Data)
  623. // 安全检查 Data,确保它是一个数组
  624. if (!Array.isArray(Data)) {
  625. console.error("Data should be an array")
  626. return result // 返回原 result 或者根据需要返回其他默认值
  627. }
  628. result = Data.map((row) => {
  629. // 获取每一行的 `code`, `name`, `value` 和 `flag`
  630. const code = row.code || " "
  631. const name = row.name || " "
  632. const value =
  633. row.value === null || row.value === undefined || row.value === ""
  634. ? " "
  635. : row.value
  636. const flag =
  637. row.flag === null || row.flag === undefined // 仅在 null 或 undefined 时替换为空格
  638. ? " "
  639. : row.flag
  640. // 将字段连接为一个以逗号分隔的字符串
  641. return `${code},${name},${value},${flag}`
  642. }).join(";") // 每行之间用分号分隔
  643. return result
  644. }
  645. const getadflow = (id,nowid) => {
  646. pid.value = id;
  647. if(nowid){
  648. wid.value = nowid;
  649. }
  650. console.log('getadflow:',pid.value,wid.value)
  651. const params = {
  652. transCode: "MDO0049",
  653. pid: pid.value,
  654. wid: wid.value
  655. }
  656. request(params)
  657. .then((res) => {
  658. if (res.hasOwnProperty("adid")) {
  659. getadflowAssign(res);
  660. writeslicesolutionChange(writeslicesolution.value);
  661. console.log('adid flow:',adid.value)
  662. emitter.emit("adidFromadflow", adid);
  663. // 默认加载cgns文件
  664. openWebSocket(res.fid);
  665. }
  666. })
  667. .catch((err) => {
  668. ElMessage.error('ADflow初始化失败')
  669. })
  670. }
  671. const getadflowAssign = (data) => {
  672. pid.value = data.pid
  673. adid.value = data.adid
  674. adflowvalue.value.gridfile = data.gridfile
  675. adflowvalue.value.fid = data.fid
  676. adflowvalue.value.proname = data.proname
  677. isairfoil.value = data.isairfoil
  678. writetecplotsurfacesolution.value = data.writetecplotsurfacesolution
  679. equationtype.value = data.equationtype
  680. liftindex.value = data.liftindex
  681. adflowvalue.value.temperature = data.temperature
  682. adflowvalue.value.cl = data.cl
  683. adflowvalue.value.cd = data.cd
  684. adflowvalue.value.cmz = data.cmz
  685. adflowvalue.value.resrho = data.resrho
  686. adflowvalue.value.length = data.length
  687. adflowvalue.value.area = data.area
  688. adflowvalue.value.momx = data.momx
  689. adflowvalue.value.momy = data.momy
  690. adflowvalue.value.momz = data.momz
  691. adflowvalue.value.mgcycle = data.mgcycle
  692. adflowvalue.value.ncycles = data.ncycles
  693. adflowvalue.value.l2convergence = data.l2convergence
  694. adflowvalue.value.l2convergencecoarse = data.l2convergencecoarse
  695. inParams.value = data.inParams
  696. outParams.value = data.outParams
  697. writeslicesolution.value = data.writeslicesolution
  698. spandirection.value = data.spandirection
  699. slices.value = data.slices
  700. }
  701. const getadflowsave = (id,nowid) => {
  702. if(nowid){
  703. wid.value = nowid
  704. }
  705. pid.value = id;
  706. const params = {
  707. transCode: "MDO0050",
  708. pid: pid.value,
  709. wid: wid.value,
  710. gridfile: adflowvalue.value.gridfile,
  711. fid: adflowvalue.value.fid,
  712. proname: adflowvalue.value.proname,
  713. isairfoil: isairfoil.value,
  714. writetecplotsurfacesolution: writetecplotsurfacesolution.value,
  715. equationtype: equationtype.value,
  716. liftindex: liftindex.value,
  717. temperature: adflowvalue.value.temperature,
  718. cl:cl.value,
  719. resrho:resrho.value,
  720. cd:cd.value,
  721. cmz:cmz.value,
  722. length: adflowvalue.value.length,
  723. area: adflowvalue.value.area,
  724. momx: adflowvalue.value.momx,
  725. momy: adflowvalue.value.momy,
  726. momz: adflowvalue.value.momz,
  727. mgcycle: adflowvalue.value.mgcycle,
  728. ncycles: adflowvalue.value.ncycles,
  729. l2convergence: adflowvalue.value.l2convergence,
  730. l2convergencecoarse: adflowvalue.value.l2convergencecoarse,
  731. writeslicesolution: writeslicesolution.value,
  732. spandirection: spandirection.value,
  733. slices: slices.value,
  734. checked: 1,
  735. inParams: convertToStringArray([], inParams.value),
  736. outParams: convertToStringArray([], outParams.value)
  737. }
  738. request(params)
  739. .then((res) => {
  740. ElMessage({
  741. message: '保存成功',
  742. type: "success"
  743. })
  744. getadflow(pid.value, wid.value);
  745. })
  746. .catch((err) => {
  747. ElMessage.error('保存失败')
  748. })
  749. }
  750. // 更新文件名
  751. const updateFileName = (newValue) => {
  752. meshFileName.value = newValue
  753. }
  754. // 更新进度条
  755. const updatePercentage = (newValue) => {
  756. percentage.value = newValue
  757. }
  758. // 控制进度条显隐
  759. const showProgress = computed(() => percentage.value > 0 && percentage.value <= 100);
  760. const fetchCgnsData = async (fpid) =>{
  761. isLoading.value = true;
  762. try {
  763. const response = await fetch('https://www.adicn.com/airopt/TransServlet', {
  764. method: 'POST',
  765. headers: {
  766. 'Content-Type': 'application/json',
  767. },
  768. body: JSON.stringify({
  769. channelNo: 'service',
  770. clientToken: 'e47b87eec69545559d1e81e56626da68',
  771. transCode: 'MDO0061',
  772. userId: '5f06c8bc77234f969d13e160b54c27e3',
  773. fid: fpid
  774. }),
  775. });
  776. }catch (error) {
  777. isLoading.value = false;
  778. console.error("请求失败:", error.response || error);
  779. }
  780. }
  781. function getUrl(channelNo = 'service') {
  782. let url = ''
  783. if (channelNo == 'service') {
  784. url = '/TransServlet'
  785. } else if (channelNo == 'manager') {
  786. url = '/managersvr/TransServlet'
  787. }
  788. return url
  789. }
  790. const getCgnsData = async (fpid) =>{
  791. let url = import.meta.env.VITE_BASE_URL + getUrl();
  792. try {
  793. const response = await fetch(url, {
  794. method: 'POST',
  795. headers: {
  796. 'Content-Type': 'application/json',
  797. },
  798. body: JSON.stringify({
  799. channelNo: 'service',
  800. clientToken: 'e47b87eec69545559d1e81e56626da68',
  801. transCode: 'MDO0062',
  802. userId: '5f06c8bc77234f969d13e160b54c27e3',
  803. fid: fpid
  804. }),
  805. });
  806. // 解析 JSON 数据
  807. const data = await response.json(); //
  808. console.log('接口返回的数据:', data); // 正确打印数据
  809. cgnsData.value = data;
  810. isLoading.value = false;
  811. }catch (error) {
  812. isLoading.value = false;
  813. console.error("请求失败:", error.response || error);
  814. }
  815. }
  816. //websockct的连接
  817. const openWebSocket = (fid) => {
  818. if (websock.value?.readyState === 1) return; // 避免重复创建
  819. const wsurl = import.meta.env.VITE_WEBSOCKET_URL + fid;
  820. const ws = new WebSocket(wsurl);
  821. websock.value = ws;
  822. ws.onopen = websocketonopen;
  823. ws.onmessage = websocketonmessage;
  824. ws.onerror = websocketonerror;
  825. ws.onclose = websocketclose;
  826. }
  827. // Websoket连接成功事件
  828. const websocketonopen = (res) => {
  829. console.log("cgnsWebSocket连接成功", res);
  830. // 开启心跳
  831. start();
  832. // 调用文件解析
  833. fetchCgnsData(adflowvalue.value.fid);
  834. };
  835. // Websoket接收消息事件
  836. const websocketonmessage = (res) => {
  837. try {
  838. const receivedData = JSON.parse(res.data);
  839. if (receivedData.status === 0) {
  840. console.log("转换成功,准备关闭");
  841. // 1. 清除所有计时器
  842. clearAllTimers();
  843. // 2. 解除事件监听
  844. websock.value.onclose = null;
  845. websock.value.onerror = null;
  846. // 3. 主动关闭(code 1000)
  847. websock.value.close(1000, "Normal closure");
  848. // 4. 置空引用
  849. websock.value = null;
  850. // 5. 获取数据
  851. getCgnsData(adflowvalue.value.fid);
  852. return; // 直接返回
  853. }
  854. } catch (e) {
  855. // 非JSON消息(如连接成功的文本提示或心跳回复)
  856. if (res.data === "建立服务端连接成功!") {
  857. console.log("WebSocket连接已建立");
  858. }
  859. else if (res.data === "服务端已经接收到消息,msg=heartCheck") {
  860. console.log("心跳确认");
  861. }
  862. else {
  863. console.warn("未知的非JSON消息:", res.data);
  864. }
  865. }
  866. reset();
  867. };
  868. // Websoket连接错误事件
  869. const websocketonerror = (res) => {
  870. console.log("连接错误", res);
  871. websock.close();
  872. reconnect();
  873. };
  874. // Websoket断开事件
  875. const websocketclose = (res) => {
  876. console.log("断开连接", res);
  877. // 只有当非正常关闭时才重连(code 1000=正常关闭)
  878. if (res.code !== 1000) {
  879. reconnect();
  880. }
  881. };
  882. // 心跳包
  883. const reconnect = () => {
  884. // 增加多个防护条件
  885. if (
  886. times.value.lockReconnect ||
  887. websock.value?.readyState === 1 ||
  888. !adflowvalue.value?.fid
  889. ) return;
  890. console.log("尝试重连...");
  891. times.value.lockReconnect = true;
  892. clearTimeout(times.value.timeoutnum);
  893. times.value.timeoutnum = setTimeout(() => {
  894. if (!websock.value || websock.value?.readyState > 1) {
  895. openWebSocket(adflowvalue.value.fid);
  896. }
  897. times.value.lockReconnect = false;
  898. }, 10000);
  899. };
  900. const reset = () => {
  901. //重置心跳
  902. clearTimeout(times.value.timeoutObj);
  903. clearTimeout(times.value.serverTimeoutObj);
  904. start();
  905. }
  906. const start = () => {
  907. clearTimeout(times.value.timeoutObj);
  908. clearTimeout(times.value.serverTimeoutObj);
  909. // 增加连接状态检查
  910. if (!websock.value || websock.value.readyState !== 1) return;
  911. times.value.timeoutObj = setTimeout(() => {
  912. if (websock.value?.readyState === 1) {
  913. websock.value.send("heartCheck");
  914. times.value.serverTimeoutObj = setTimeout(() => {
  915. if (websock.value?.readyState === 1) {
  916. websock.value.close(1006, "Heartbeat timeout");
  917. }
  918. }, times.value.timeout);
  919. }
  920. }, times.value.heartBeatInterval);
  921. }
  922. const clearAllTimers = () => {
  923. clearTimeout(times.value.timeoutObj);
  924. clearTimeout(times.value.serverTimeoutObj);
  925. clearTimeout(times.value.timeoutnum);
  926. times.value.lockReconnect = true; // 永久锁定重连
  927. };
  928. // 处理上传成功后的逻辑
  929. const handleFileUploadSuccess = (newValue) => {
  930. //隐藏进度条
  931. setTimeout(() => {
  932. percentage.value = 0;
  933. }, 1000);
  934. adflowvalue.value.gridfile = newValue.fname;
  935. adflowvalue.value.fid = newValue.bfid;
  936. console.log("文件上传成功,bfid:", newValue.bfid, "fname:", newValue.fname)
  937. // 开启websocket
  938. openWebSocket(newValue.bfid);
  939. }
  940. // 更新上传状态
  941. const getUploadStatus = (newValue) => {
  942. uploadStatus.value = newValue
  943. }
  944. const fileDel = () => {
  945. }
  946. // onMounted(() => {
  947. // emitter.on("requestGetadid", getadflow); // 监听事件
  948. // });
  949. // onUnmounted(() => {
  950. // emitter.off("requestGetadid", getadflow); // 解绑事件
  951. // });
  952. defineExpose({
  953. getadflow,
  954. getadflowAssign,
  955. getadflowsave
  956. })
  957. </script>