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