index.vue 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093
  1. <template>
  2. <div class="dataAnalysisPosAnal" :class="!theme ? 'themeDark' : 'themeLight'">
  3. <div class="dataAnalysisPosAnalMain">
  4. <div class="main_top">
  5. <p class="topPsty">微观选址分析</p>
  6. </div>
  7. <div class="main">
  8. <div class="treeDataMain">
  9. <tree-cop
  10. ref="treeCopRef"
  11. :data="treeData"
  12. @checkChange="funTreeCheckChange"
  13. :show-checkbox="true"
  14. :height="treeHeight"
  15. @currentChange="funCurrentChange"
  16. @refresh="funGetTree"
  17. ></tree-cop>
  18. </div>
  19. <div class="excelDataMain">
  20. <excel-cop
  21. :checkIds="excelCheckIds"
  22. :showCheckbox="excelCheckboxShow"
  23. :data="excelList"
  24. :theme="theme"
  25. :height="excelHeight"
  26. @excelChange="funExcelChange"
  27. @checkChange="funExcelCheckChange"
  28. >
  29. </excel-cop>
  30. </div>
  31. <div class="tableDataMain">
  32. <div class="shadow rounded-[6px] shadow-blue-500 overflow-hidden">
  33. <div
  34. :style="{
  35. height:
  36. typeof tableHeight === 'string'
  37. ? tableHeight
  38. : tableHeight + 'px',
  39. overflow: 'hidden',
  40. }"
  41. >
  42. <!-- <posChart @mapDone="funMapDone" @rightClick="funRightClick" :height="tableHeight"
  43. :windList="windList" :ids="excelCheckIds" v-if="showOnlineMap" /> -->
  44. <!-- v-if="showOnlineMap" -->
  45. <!-- <kMap
  46. :parentId="treeId"
  47. :ids="excelCheckIds"
  48. @mapDone="funMapDone"
  49. @rightClick="funRightClick"
  50. /> -->
  51. <leafletMap
  52. :windList="windList"
  53. :ids="excelCheckIds"
  54. @mapDone="funMapDone"
  55. @rightClick="funRightClick"
  56. />
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. </div>
  62. <el-dialog
  63. draggable
  64. width="80%"
  65. top="10px"
  66. v-model="dbRateDialog"
  67. :title="actDiaTitle"
  68. modal-class="rightMenuDialog"
  69. >
  70. <el-form class="whitespace-nowrap" :inline="true" :model="queryForm">
  71. <el-form-item label="" class="!mb-0">
  72. <el-select
  73. style="width: 120px"
  74. v-model="queryForm.checkIds"
  75. clearable
  76. @clear="checkAll = false"
  77. collapse-tags
  78. multiple
  79. >
  80. <el-option
  81. label="全选"
  82. :class="{ selected: checkAll }"
  83. @click="funCheckAll"
  84. ></el-option>
  85. <el-option
  86. v-for="item in windList"
  87. :key="item.processId"
  88. :value="item.processId"
  89. :label="item.name"
  90. ></el-option>
  91. </el-select>
  92. </el-form-item>
  93. <el-form-item class="!mb-0">
  94. <submit-btn desc="查询" @click="funDiaSubmit"></submit-btn>
  95. <submit-btn desc="导出" @click="funDiaExport"></submit-btn>
  96. </el-form-item>
  97. </el-form>
  98. <div v-loading="exportLoading">
  99. <div
  100. style="height: 600px"
  101. class="flex flex-wrap justify-center items-center overflow-y-auto overflow-x-hidden"
  102. ref="diaPanelRef"
  103. >
  104. <component
  105. :is="item.actCop"
  106. :width="`${100 / (actCopList.length || 1)}%`"
  107. height="100%"
  108. v-for="item in actCopList"
  109. :key="item.id"
  110. :xAxis="item.xAxis"
  111. :subtext="item.subtext"
  112. :isRadar="item.isRadar"
  113. :title="item.title"
  114. :series="item.series"
  115. :isDiaAlone="actCopList.length === 1"
  116. @dblclick="funDbClick(item)"
  117. :yAxis="item.yAxis"
  118. :dataset="item.dataset"
  119. :brush="item.isBrush"
  120. :count="item.count || []"
  121. ></component>
  122. </div>
  123. </div>
  124. </el-dialog>
  125. <el-dialog
  126. custom-class="windLifeDialog"
  127. title="对风偏差分析"
  128. draggable
  129. width="90%"
  130. top="25px"
  131. v-model="rateDialog"
  132. >
  133. <el-row :style="{ height: '793px' }">
  134. <el-col
  135. :span="12"
  136. v-for="(item, index) in chartData"
  137. :key="item.id"
  138. style="height: 45%"
  139. >
  140. <el-icon
  141. :style="!theme ? 'color: #fff' : ''"
  142. size="18"
  143. @click="funActCop(item, 'chartCop' + (index + 1))"
  144. >
  145. <ZoomIn />
  146. </el-icon>
  147. <chart-cop
  148. class=""
  149. height="100%"
  150. width="100%"
  151. :xAxis="item.xAxis"
  152. :isRadar="item.isRadar"
  153. :theme="theme"
  154. :echartsTheme="echartsTheme"
  155. :subtext="item.subtext"
  156. :title="item.title"
  157. :series="item.series"
  158. >
  159. </chart-cop>
  160. </el-col>
  161. <el-col :span="12" v-if="!!lineSeries.length" style="height: 50%">
  162. <el-icon
  163. :style="!theme ? 'color: #fff' : ''"
  164. size="18"
  165. @click="
  166. funActCop(
  167. {
  168. xAxis: linexAxis,
  169. yAxis: lineyAxis,
  170. series: lineSeries,
  171. dataset: lineDataSet,
  172. },
  173. 'lineChartCop'
  174. )
  175. "
  176. >
  177. <ZoomIn />
  178. </el-icon>
  179. <line-chart-cop
  180. class=""
  181. height="100%"
  182. width="100%"
  183. :xAxis="linexAxis"
  184. :yAxis="lineyAxis"
  185. :theme="theme"
  186. :echartsTheme="echartsTheme"
  187. :series="lineSeries"
  188. subtext="对风偏差分析图"
  189. :dataset="lineDataSet"
  190. ></line-chart-cop>
  191. </el-col>
  192. <el-col :span="12" v-if="!!lineSeries.length" style="height: 50%">
  193. <el-icon
  194. :style="!theme ? 'color: #fff' : ''"
  195. size="18"
  196. @click="
  197. funActCop(
  198. {
  199. xAxis: scatterxData,
  200. yAxis: scatteryData,
  201. series: scatterSeries,
  202. },
  203. 'scatterSingleChartCop'
  204. )
  205. "
  206. >
  207. <ZoomIn />
  208. </el-icon>
  209. <scatter-single-chart-cop
  210. class=""
  211. height="95%"
  212. width="100%"
  213. :xAxis="scatterxData"
  214. :theme="theme"
  215. :echartsTheme="echartsTheme"
  216. :yAxis="scatteryData"
  217. :series="scatterSeries"
  218. subtext="静态偏航对风分析图"
  219. >
  220. </scatter-single-chart-cop>
  221. </el-col>
  222. </el-row>
  223. </el-dialog>
  224. <el-dialog
  225. custom-class="windLifeDialog"
  226. title="功率曲线拟合"
  227. draggable
  228. width="90%"
  229. top="25px"
  230. modal-class="rightMenuDialog"
  231. v-model="combineDialog"
  232. >
  233. <combineChart
  234. width="100%"
  235. height="600px"
  236. :chartTitle="
  237. avgObj.title +
  238. '&nbsp;&nbsp;' +
  239. '平均Cp值:' +
  240. avgObj.cpavg +
  241. '; 静风频率:' +
  242. avgObj.frequency +
  243. '%; 曲线偏差率:' +
  244. avgObj.pcratio +
  245. '%'
  246. "
  247. :xAxisData="combine.xAxisData"
  248. :yAxisData="{ splitLine: { show: false } }"
  249. :seriesData="combine.seriesData"
  250. :theme="theme"
  251. :echartsTheme="echartsTheme"
  252. :showLegend="true"
  253. :brushSelected="!combine.isChartArea"
  254. :dataSet="combine.dataSet"
  255. @getSelected="funCombineChartSelect"
  256. ></combineChart>
  257. </el-dialog>
  258. <!-- 功率曲线拟合的圈选功能 -->
  259. <el-dialog v-model="wtDialog" draggable title="风机功率点位">
  260. <el-tabs v-model="wtTab">
  261. <el-tab-pane label="数据" name="table">
  262. <el-table
  263. :data="wtData"
  264. default-expand-all
  265. row-key="id"
  266. :max-height="550"
  267. >
  268. <el-table-column property="wtId" align="center" label="风机" />
  269. <el-table-column
  270. property="time"
  271. sortable
  272. :width="160"
  273. align="center"
  274. label="时间"
  275. />
  276. <el-table-column
  277. property="speed"
  278. sortable
  279. align="center"
  280. label="风速(m/s)"
  281. />
  282. <el-table-column
  283. property="power"
  284. sortable
  285. align="center"
  286. label="功率(kW)"
  287. />
  288. <el-table-column
  289. property="rr"
  290. sortable
  291. align="center"
  292. label="转速"
  293. />
  294. <el-table-column
  295. property="filter"
  296. sortable
  297. align="center"
  298. label="是否有用点"
  299. />
  300. </el-table>
  301. </el-tab-pane>
  302. <el-tab-pane label="故障" name="problem" disabled> </el-tab-pane>
  303. <el-tab-pane label="预警" name="warning" disabled> </el-tab-pane>
  304. </el-tabs>
  305. </el-dialog>
  306. <el-dialog
  307. custom-class="windLifeDialog"
  308. title="曲线偏差率分析"
  309. draggable
  310. width="90%"
  311. top="25px"
  312. modal-class="rightMenuDialog"
  313. v-model="lineDialog"
  314. >
  315. <combineChart
  316. ref="chartRef"
  317. width="100%"
  318. height="600px"
  319. :chartTitle="qxLineChartTitle"
  320. :xAxisData="qxLineChart.xAxisData"
  321. :yAxisData="{ splitLine: { show: false } }"
  322. :seriesData="qxLineChart.seriesData"
  323. :showLegend="true"
  324. :brushSelected="false"
  325. :dataSet="qxLineChart.dataSet"
  326. :theme="theme"
  327. :echartsTheme="echartsTheme"
  328. :showToolbox="false"
  329. tooltipTrigger="axis"
  330. @getSelected="qxLineChart.funChartSelect"
  331. />
  332. </el-dialog>
  333. <el-dialog
  334. custom-class="windLifeDialog"
  335. title="温度与功率分析"
  336. draggable
  337. width="90%"
  338. top="25px"
  339. modal-class="rightMenuDialog"
  340. v-model="hotDialog"
  341. >
  342. <combineChart
  343. ref="chartRef"
  344. width="100%"
  345. height="600px"
  346. :chartTitle="
  347. avgObj.title +
  348. '&nbsp;&nbsp;' +
  349. '平均Cp值:' +
  350. avgObj.cpavg +
  351. '; 静风频率:' +
  352. avgObj.frequency +
  353. '%; 曲线偏差率:' +
  354. avgObj.pcratio +
  355. '%'
  356. "
  357. :xAxisData="hotChart.xAxisData"
  358. :yAxisData="{ splitLine: { show: false } }"
  359. :seriesData="hotChart.seriesData"
  360. :showLegend="true"
  361. :brushSelected="false"
  362. :maxMinData="hotChart.maxMinData"
  363. :theme="theme"
  364. :echartsTheme="echartsTheme"
  365. :dataSet="hotChart.dataSet"
  366. :showToolbox="false"
  367. tooltipTrigger="axis"
  368. @getSelected="funhotChartSelect"
  369. />
  370. </el-dialog>
  371. <el-dialog
  372. custom-class="windLifeDialog"
  373. title="损失电量分析"
  374. draggable
  375. width="90%"
  376. top="25px"
  377. modal-class="rightMenuDialog"
  378. v-model="ssDialog"
  379. >
  380. <bar-line-chart-cop
  381. height="600px"
  382. :bardata="ssChart.barData"
  383. :lineData="ssChart.lineData"
  384. :color="ssChart.barColor"
  385. lineName="理论发电量"
  386. ></bar-line-chart-cop>
  387. </el-dialog>
  388. <el-dialog
  389. custom-class="windLifeDialog"
  390. title="桨距角分析"
  391. draggable
  392. width="90%"
  393. top="25px"
  394. modal-class="rightMenuDialog"
  395. v-model="jjjDialog"
  396. >
  397. <div class="tableDataMain">
  398. <el-tabs v-model="jjjActiveTab">
  399. <el-tab-pane label="图表展示" name="1">
  400. <div style="height: 600px">
  401. <combineChart
  402. ref="chartRef"
  403. width="100%"
  404. height="100%"
  405. :chartTitle="''"
  406. style="margin-top: 3vh"
  407. :xAxisData="jjjChart.xAxisData"
  408. :yAxisData="{ splitLine: { show: false } }"
  409. :seriesData="jjjChart.seriesData"
  410. :seriesAllData="jjjChart.seriesAllData"
  411. :showLegend="true"
  412. :brushSelected="false"
  413. :dataSet="jjjChart.dataSet"
  414. :theme="theme"
  415. :echartsTheme="echartsTheme"
  416. @getSelected="funChartSelect"
  417. />
  418. </div>
  419. </el-tab-pane>
  420. <el-tab-pane label="桨距角风速曲线" name="2" v-if="false">
  421. <div style="height: 600px">
  422. <!-- <div id="speedLine" style="width:100%;height:100%"></div> -->
  423. <bar-chart-cop
  424. width="100%"
  425. height="100%"
  426. :theme="theme"
  427. :echartsTheme="echartsTheme"
  428. :xAxis="jjjChart.linexAxis"
  429. :yAxis="jjjChart.lineyAxis"
  430. :series="jjjChart.lineSeries"
  431. ></bar-chart-cop>
  432. </div>
  433. </el-tab-pane>
  434. <el-tab-pane label="表格数据" name="3">
  435. <div style="height: 600px">
  436. <table-cop
  437. class=""
  438. :data="jjjChart.tableData"
  439. :column="jjjChart.tableColumn"
  440. :theme="theme"
  441. height="100%"
  442. tableId="1"
  443. :tableName="jjjChart.tableName"
  444. :rowstyle="true"
  445. ></table-cop>
  446. </div>
  447. </el-tab-pane>
  448. </el-tabs>
  449. </div>
  450. </el-dialog>
  451. </div>
  452. </template>
  453. <script setup name="prepare">
  454. import excelCop from "@/components/generatingCapacityComponent/excel.vue";
  455. import treeCop from "@/components/generatingCapacityComponent/tree.vue";
  456. import {
  457. ref,
  458. nextTick,
  459. onActivated,
  460. shallowRef,
  461. onMounted,
  462. reactive,
  463. watch,
  464. } from "vue";
  465. import axios from "axios";
  466. import { useRouter } from "vue-router";
  467. import { useStore } from "vuex";
  468. import { ElMessage } from "element-plus";
  469. import tools from "@tools/htmlToPdf.js";
  470. import posChart from "./components/posChart.vue";
  471. import leafletMap from "./components/leafletMap.vue";
  472. /**combine */
  473. import combineChart from "../combine/components/current-scatter-chart.vue";
  474. /**rateAnalysis */
  475. import barLineChartCop from "../combine/components/barLineChart.vue";
  476. import barChartCop from "../combine/components/barChart.vue";
  477. import chartCop from "../rateAnalysis/components/chart.vue";
  478. import lineChartCop from "../rateAnalysis/components/lineChart.vue";
  479. import scatterSingleChartCop from "../rateAnalysis/components/scatterSingleChart.vue";
  480. import kMap from "@/components/generatingCapacityComponent/kMap/index.vue";
  481. import httpRequest from "@/utils/request.js";
  482. import jsonData from "./components/data.json";
  483. const router = useRouter();
  484. /**配置参数 */
  485. const treeHeight = ref(window.innerHeight - 115 + "px"); //tree高度
  486. const excelHeight = ref(window.innerHeight - 115 + "px"); //excel高度
  487. const tableHeight = ref(window.innerHeight - 115 + "px");
  488. /**excel 开始 */
  489. const excelCheckboxShow = ref(false);
  490. const excelCheckIds = ref([]);
  491. const excelList = ref([]);
  492. const store = useStore();
  493. const showOnlineMap = ref(false);
  494. watch(
  495. () => router.currentRoute.value,
  496. (newValue, oldValue) => {
  497. // if (newValue.path === "/dataAnalysis/posAnalysis") {
  498. if (newValue.path.indexOf("/dataAnalysis/posAnalysis") > -1) {
  499. if (newValue.query.onlineMap) {
  500. showOnlineMap.value = newValue.query.onlineMap === "1" ? false : true;
  501. }
  502. }
  503. },
  504. {
  505. immediate: true,
  506. }
  507. );
  508. const funExcelChange = async (obj) => {
  509. //点击excel项时
  510. return false;
  511. };
  512. const funExcelCheckChange = ({ checkArr, data }) => {
  513. //bug
  514. excelCheckIds.value = checkArr;
  515. funSubmit();
  516. };
  517. /**prepare tree 开始 */
  518. const treeData = ref([]);
  519. const treeCopRef = ref(); //treeCop ref
  520. const actTreeNode = ref(null); //当前激活的treeNode
  521. const funRepeatMap = (arr, type = "fitting") => {
  522. return arr.map((o) => {
  523. if (o.children) {
  524. const findIndex = o.children.findIndex((p) => !!p.type);
  525. if (findIndex !== -1) {
  526. o.childs = o.children;
  527. o.children = [];
  528. if (!actTreeNode.value && type === "fitting") {
  529. //判断当且仅有process获取tree时 赋值
  530. actTreeNode.value = o;
  531. }
  532. }
  533. }
  534. return {
  535. ...o,
  536. children: o.children ? funRepeatMap(o.children, type) : [],
  537. };
  538. });
  539. };
  540. const funGetTree = async () => {
  541. actTreeNode.value = null;
  542. const res = await httpRequest.get("/power/fitting/tree");
  543. treeData.value = funRepeatMap(res.data);
  544. excelList.value = [];
  545. if (actTreeNode.value) {
  546. funCurrentChange({
  547. current: actTreeNode.value,
  548. currentNode: null,
  549. });
  550. if (treeCopRef.value) {
  551. treeCopRef.value.$refs.tree.setCheckedKeys([actTreeNode.value.id]);
  552. excelCheckIds.value = actTreeNode.value.childs.map((o) => o.id);
  553. funSubmit();
  554. }
  555. }
  556. };
  557. const treeId = ref("");
  558. const funCurrentChange = ({ current, currentNode }) => {
  559. excelCheckboxShow.value = true;
  560. if (current.childs) {
  561. excelList.value = current.childs.map((o) => {
  562. return {
  563. id: o.id,
  564. interval: o.interval,
  565. path: o.path,
  566. prepareid: o.prepareid,
  567. station: o.station,
  568. time: o.time,
  569. type: o.type,
  570. windturbine: o.windturbine,
  571. name: o.path.substring(
  572. o.path.indexOf(o.station + "_") + (o.station + "_").length
  573. ),
  574. };
  575. });
  576. // excelCheckIds.value = current.childs.map((o) => o.id);
  577. // treeId.value = current.id || "";
  578. funSubmit();
  579. } else {
  580. excelList.value = [];
  581. excelCheckIds.value = [];
  582. windList.value = [];
  583. }
  584. };
  585. const funTreeCheckChange = ({
  586. current,
  587. checkedNodes,
  588. checkedKeys,
  589. halfCheckedNodes,
  590. halfCheckedKeys,
  591. }) => {
  592. funCurrentChange({
  593. current,
  594. currentNode: "",
  595. });
  596. const checkIds = [];
  597. if (checkedNodes.checkedNodes.length) {
  598. let checkArr = checkedNodes.checkedNodes;
  599. checkArr.forEach((it) => {
  600. if (it.childs && it.childs.length) {
  601. it.childs.forEach((iv) => {
  602. checkIds.push(iv.id);
  603. });
  604. }
  605. });
  606. }
  607. excelCheckIds.value = checkIds;
  608. //tree change -> excel change
  609. // funCurrentChange({ current, currentNode: '' })
  610. // const checkIds = []
  611. // if (checkedNodes.length) {
  612. // for (const node of checkedNodes) {
  613. // if (node.childs && node.childs.length) {
  614. // for (const child of node.childs) {
  615. // checkIds.push(child.id)
  616. // }
  617. // }
  618. // }
  619. // }else{
  620. // windList.value = []
  621. // }
  622. // excelCheckIds.value = checkIds
  623. // funSubmit()
  624. };
  625. /**search 开始 */
  626. const funSubmit = async () => {
  627. // if (!excelCheckIds.value.length) {
  628. // ElMessage.error('请勾选要执行的项')
  629. // return false
  630. // }
  631. const params = {
  632. ids: excelCheckIds.value.join(","),
  633. };
  634. const res = await httpRequest.get("/base/location", {
  635. params: params,
  636. });
  637. let windList = [];
  638. res.data.forEach((ele) => {
  639. if (ele.longitude && ele.latitude) {
  640. windList.push(ele);
  641. }
  642. });
  643. windList.value = windList;
  644. };
  645. /**posChart */
  646. const windList = ref([]);
  647. const funRightClick = ({ menuIndex, current }) => {
  648. switch (menuIndex) {
  649. case 0:
  650. funCombineGet(current);
  651. break;
  652. case 1:
  653. funRateSubmit(current);
  654. queryForm.checkIds = windList.value.map((o) => o.processId);
  655. break;
  656. case 2:
  657. funLineSubmit(current);
  658. break;
  659. case 3:
  660. funHotSubmit(current);
  661. break;
  662. case 4:
  663. funSsSubmit(current);
  664. break;
  665. case 5:
  666. funJjjSubmit(current);
  667. break;
  668. }
  669. };
  670. const lineDialog = ref(false);
  671. const qxLineChartTitle = ref("");
  672. const qxLineChart = reactive({
  673. xAxisData: [],
  674. seriesData: [],
  675. dataSet: "",
  676. isChartArea: false,
  677. });
  678. const funLineSubmit = async (current) => {
  679. const params = {
  680. // ids: current.processId,
  681. ids: current.fittingId,
  682. };
  683. const res = await httpRequest.get("/power/fitting/line", {
  684. params: params,
  685. });
  686. if (res.code === 200) {
  687. qxLineChart.seriesData = [];
  688. if (res?.data?.bzgl) {
  689. qxLineChart.seriesData.push({
  690. name: "保证功率",
  691. type: "line",
  692. symbol: "line", //设定为实心点
  693. symbolSize: 0, //设定实心点的大小
  694. smooth: true, //这个是把线变成曲线
  695. data: res.data.bzgl || [],
  696. xAxisIndex: 0,
  697. });
  698. }
  699. if (res?.data?.sjgl) {
  700. res.data.sjgl.forEach((ele) => {
  701. qxLineChart.seriesData.push({
  702. name: "实际功率",
  703. type: "line",
  704. symbol: "line", //设定为实心点
  705. symbolSize: 0, //设定实心点的大小
  706. smooth: true, //这个是把线变成曲线
  707. data: ele.sjgl || [],
  708. xAxisIndex: 0,
  709. });
  710. });
  711. }
  712. qxLineChartTitle.value = current.name;
  713. lineDialog.value = true;
  714. }
  715. };
  716. const hotDialog = ref(false);
  717. const hotChart = reactive({
  718. xAxisData: [],
  719. seriesData: [],
  720. dataSet: "",
  721. isChartArea: false,
  722. maxMinData: [],
  723. });
  724. const funHotSubmit = async (obj) => {
  725. let chartRes = {
  726. scatterhs: [[]],
  727. scatterls: [[]],
  728. sjgl: [[]],
  729. llgl: [[]],
  730. cpz: [[]],
  731. };
  732. let chartResponse = null;
  733. chartResponse = await httpRequest.get("/temperature/curve/analysis", {
  734. params: {
  735. id: obj.fittingId,
  736. p: 1,
  737. },
  738. });
  739. if (chartResponse && chartResponse.code === 200) {
  740. chartRes = chartResponse.data;
  741. hotChart.maxMinData = [chartRes.maxhjwd, chartRes.minhjwd];
  742. avgObj.title = chartRes.obj.path
  743. .substring(
  744. chartRes.obj.path.indexOf(chartRes.obj.station + "_") +
  745. (chartRes.obj.station + "_").length
  746. )
  747. .split("_")[0];
  748. avgObj.cpavg = Number(chartRes.obj.cpavg).toFixed(2);
  749. avgObj.frequency = Number(chartRes.obj.frequency).toFixed(2);
  750. avgObj.pcratio = Number(chartRes.obj.pcratio).toFixed(2);
  751. const color = [
  752. "#1C99FF",
  753. "#FF8700",
  754. "#3D54BE",
  755. "#fa8c16",
  756. "#1DA0D7",
  757. "#DD5044",
  758. ];
  759. hotChart.seriesData = [
  760. {
  761. name: "拟合功率",
  762. type: "line",
  763. symbol: "line", //设定为实心点
  764. symbolSize: 0, //设定实心点的大小
  765. smooth: true, //这个是把线变成曲线
  766. data: chartRes.sjgl,
  767. xAxisIndex: 0,
  768. },
  769. {
  770. name: "保证功率",
  771. type: "line",
  772. symbol: "line", //设定为实心点
  773. symbolSize: 0, //设定实心点的大小
  774. smooth: true, //这个是把线变成曲线
  775. data: chartRes.llgl,
  776. xAxisIndex: 0,
  777. },
  778. {
  779. type: "effectScatter",
  780. showEffectOn: "emphasis",
  781. rippleEffect: {
  782. scale: 1,
  783. },
  784. name: "数据散点",
  785. symbolSize: 5,
  786. // symbolSize: (data) => {
  787. // return data.s ? data.s > 10 ? 10 : data.s : 4
  788. // },
  789. // datasetIndex: 1,
  790. // encode: {
  791. // x: 'x',
  792. // y: 'y'
  793. // },
  794. data: chartRes.scatter,
  795. xAxisIndex: 0,
  796. yAxisIndex: 0,
  797. },
  798. ];
  799. hotDialog.value = true;
  800. }
  801. };
  802. const ssDialog = ref(false);
  803. const ssChart = reactive({
  804. barData: [],
  805. lineData: [],
  806. color: [
  807. "#4b55ae",
  808. "#e17e23",
  809. "#ba3237",
  810. "#c531c7",
  811. "rgb(63,177,227)",
  812. "#05bb4c",
  813. ],
  814. });
  815. const funSsSubmit = async (obj) => {
  816. ssChart.barData = {
  817. area: [],
  818. legend: [],
  819. data: [],
  820. };
  821. ssChart.lineData = [];
  822. const res = await httpRequest.get("/fjjxb/five/loss/cal", {
  823. params: {
  824. ids: obj.fittingId,
  825. },
  826. });
  827. const name = [],
  828. data = [],
  829. llfdl = [],
  830. legend = [
  831. {
  832. name: "实际电量",
  833. icon: "rect",
  834. },
  835. {
  836. name: "计划检修损失",
  837. icon: "rect",
  838. },
  839. {
  840. name: "非计划检修损失",
  841. icon: "rect",
  842. },
  843. {
  844. name: "限电损失",
  845. icon: "rect",
  846. },
  847. {
  848. name: "受累损失",
  849. icon: "rect",
  850. },
  851. {
  852. name: "性能损失",
  853. icon: "rect",
  854. },
  855. {
  856. name: "理论发电量",
  857. icon: "circle",
  858. },
  859. ],
  860. data2 = []; //项目列表
  861. res.data.data.forEach((item, index) => {
  862. name.push(item.name);
  863. data.push([item.sjfdl, item.jhjx, item.fjhjx, item.xd, item.sl, item.xn]);
  864. llfdl.push(item.llfdl);
  865. data2.push({
  866. index: index + 1,
  867. name: item.name,
  868. llfdl: item.llfdl,
  869. sjfdl: item.sjfdl,
  870. speed: item.speed,
  871. fjhjx: item.fjhjx,
  872. jhjx: item.jhjx,
  873. sl: item.sl,
  874. xd: item.xd,
  875. xn: item.xn,
  876. fnlly: item.fnlly,
  877. is_light: false,
  878. });
  879. });
  880. if (data.length > 0) {
  881. let arr1 = [];
  882. const length = data[0].length;
  883. for (var i = 0; i < length; i++) {
  884. let arr2 = [];
  885. data.forEach((ele) => {
  886. arr2.push(ele[i]);
  887. });
  888. arr1.push(arr2);
  889. }
  890. ssChart.lineData = llfdl;
  891. ssChart.barData = {
  892. area: name,
  893. legend: legend,
  894. data: arr1,
  895. };
  896. }
  897. ssChart.value = ssChart;
  898. console.log(123123, ssChart.value);
  899. ssDialog.value = true;
  900. };
  901. const jjjDialog = ref(false);
  902. const jjjActiveTab = ref("1");
  903. const jjjChart = reactive({
  904. tableData: [],
  905. tableColumn: [],
  906. tableName: "",
  907. xAxisData: [],
  908. seriesData: [],
  909. seriesAllData: [],
  910. linexAxis: [],
  911. lineyAxis: [],
  912. lineSeries: [],
  913. dataSet: [],
  914. });
  915. const funJjjSubmit = async (obj) => {
  916. const res = await httpRequest.get("/blade/angle", {
  917. params: {
  918. ids: obj.fittingId,
  919. },
  920. });
  921. let exTime = [];
  922. let yp1 = [],
  923. yp2 = [],
  924. yp3 = [],
  925. speed = [];
  926. res.data.bw.forEach((it) => {
  927. exTime.push(it.time);
  928. yp1.push(it.yp1);
  929. yp2.push(it.yp2);
  930. yp3.push(it.yp3);
  931. speed.push(it.speed);
  932. });
  933. jjjChart.tableData = res.data.bw;
  934. jjjChart.seriesAllData = res.data.bw;
  935. jjjChart.xAxisData = exTime;
  936. jjjChart.seriesData = [
  937. {
  938. name: "叶片1",
  939. type: "line",
  940. symbol: "line", //设定为实心点
  941. symbolSize: 0, //设定实心点的大小
  942. smooth: false, //这个是把线变成曲线
  943. data: yp1,
  944. xAxisIndex: 0,
  945. },
  946. {
  947. name: "叶片2",
  948. type: "line",
  949. symbol: "line", //设定为实心点
  950. symbolSize: 0, //设定实心点的大小
  951. smooth: false, //这个是把线变成曲线
  952. data: yp2,
  953. xAxisIndex: 0,
  954. },
  955. {
  956. name: "叶片3",
  957. type: "line",
  958. symbol: "line", //设定为实心点
  959. symbolSize: 0, //设定实心点的大小
  960. smooth: false, //这个是把线变成曲线
  961. data: yp3,
  962. xAxisIndex: 0,
  963. },
  964. {
  965. name: "风速",
  966. type: "line",
  967. yAxisIndex: 1,
  968. symbol: "line", //设定为实心点
  969. symbolSize: 0, //设定实心点的大小
  970. smooth: false, //这个是把线变成曲线
  971. data: speed,
  972. xAxisIndex: 0,
  973. },
  974. ];
  975. jjjDialog.value = true;
  976. };
  977. /**combine-chart */
  978. const combineDialog = ref(false);
  979. const avgObj = reactive({
  980. //平均cpz等
  981. title: "",
  982. cpavg: "",
  983. frequency: "",
  984. pcratio: "",
  985. });
  986. const markDot = reactive({
  987. //3-5 point点等
  988. pcl5: null,
  989. pcl10: null,
  990. pcl12: null,
  991. pcl25: null,
  992. });
  993. const combine = reactive({
  994. xAxisData: [],
  995. seriesData: [],
  996. dataSet: "",
  997. isChartArea: false,
  998. });
  999. const wtDialog = ref(false);
  1000. const wtData = ref([]);
  1001. const wtTab = ref("table");
  1002. const funCombineChartSelect = async (batch) => {
  1003. const wDataArr = [];
  1004. const yDataArr = [];
  1005. let scatterls = [];
  1006. let scatterhs = [];
  1007. let dataSetObj = [];
  1008. wtData.value = [];
  1009. if (batch.length && combine.dataSet) {
  1010. scatterls = batch[0].selected[2].dataIndex;
  1011. scatterhs = batch[0].selected[3].dataIndex;
  1012. if (scatterls.length || scatterhs.length) {
  1013. dataSetObj = JSON.parse(combine.dataSet);
  1014. if (scatterls.length) {
  1015. for (const scatterIndex of scatterls) {
  1016. wDataArr.push(dataSetObj[0].source[scatterIndex].k);
  1017. }
  1018. }
  1019. if (scatterhs.length) {
  1020. for (const scatterIndex of scatterhs) {
  1021. yDataArr.push(dataSetObj[1].source[scatterIndex].k);
  1022. }
  1023. }
  1024. const wtRes = await httpRequest.get("/power/fitting/filter", {
  1025. params: {
  1026. yk: yDataArr.join(","),
  1027. wk: wDataArr.join(","),
  1028. },
  1029. });
  1030. if (wtRes.code === 200) {
  1031. let id = 1;
  1032. const tempArr = []; //用于以风机id 聚合dataArr
  1033. if (wtRes.data.length) {
  1034. for (const data of wtRes.data) {
  1035. if (tempArr.length) {
  1036. const findIndex = tempArr.findIndex((o) => o.wtId === data.wtId);
  1037. if (findIndex !== -1) {
  1038. if (!tempArr[findIndex].children) {
  1039. tempArr[findIndex].children = [];
  1040. }
  1041. tempArr[findIndex].children.push({
  1042. ...data,
  1043. id: id,
  1044. filter: data.filter === 0 ? "是" : "否",
  1045. });
  1046. id++;
  1047. } else {
  1048. tempArr.push({
  1049. ...data,
  1050. id: id,
  1051. filter: data.filter === 0 ? "是" : "否",
  1052. });
  1053. id++;
  1054. }
  1055. } else {
  1056. tempArr.push({
  1057. ...data,
  1058. id: id,
  1059. filter: data.filter === 0 ? "是" : "否",
  1060. });
  1061. id++;
  1062. }
  1063. }
  1064. wtDialog.value = true;
  1065. nextTick(() => {
  1066. wtTab.value = "table";
  1067. wtData.value = tempArr;
  1068. });
  1069. }
  1070. }
  1071. }
  1072. }
  1073. };
  1074. const funCombineGet = async (obj) => {
  1075. //点击excel项时
  1076. combine.isChartArea = false;
  1077. let res = null;
  1078. let chartRes = {
  1079. scatterhs: [[]],
  1080. scatterls: [[]],
  1081. sjgl: [[]],
  1082. llgl: [[]],
  1083. cpz: [[]],
  1084. };
  1085. const chartResponse = await httpRequest.get("/power/fitting/curve", {
  1086. params: {
  1087. id: obj.fittingId,
  1088. p: 1,
  1089. },
  1090. });
  1091. if (chartResponse && chartResponse.code === 200) {
  1092. nextTick(() => {
  1093. chartRes = chartResponse.data;
  1094. markDot.pcl5 = chartRes.obj.pc5ratio;
  1095. markDot.pcl10 = chartRes.obj.pc10ratio;
  1096. markDot.pcl12 = chartRes.obj.pc12ratio;
  1097. markDot.pcl25 = chartRes.obj.pc25ratio;
  1098. avgObj.title = chartRes.obj.path
  1099. .substring(
  1100. chartRes.obj.path.indexOf(chartRes.obj.station + "_") +
  1101. (chartRes.obj.station + "_").length
  1102. )
  1103. .split("_")[0];
  1104. avgObj.cpavg = Number(chartRes.obj.cpavg).toFixed(2);
  1105. avgObj.frequency = Number(chartRes.obj.frequency).toFixed(2);
  1106. avgObj.pcratio = Number(chartRes.obj.pcratio).toFixed(2);
  1107. combine.dataSet = JSON.stringify([
  1108. {
  1109. source: chartRes.wyd,
  1110. // source: chartRes.scatterls
  1111. },
  1112. {
  1113. source: chartRes.yyd,
  1114. // source: chartRes.scatterhs
  1115. },
  1116. ]);
  1117. const color = [
  1118. "#1C99FF",
  1119. "#FF8700",
  1120. "#3D54BE",
  1121. "#fa8c16",
  1122. "#1DA0D7",
  1123. "#DD5044",
  1124. ];
  1125. combine.seriesData = [
  1126. {
  1127. name: "拟合功率",
  1128. type: "line",
  1129. symbol: "line", //设定为实心点
  1130. symbolSize: 0, //设定实心点的大小
  1131. smooth: true, //这个是把线变成曲线
  1132. data: chartRes.sjgl,
  1133. xAxisIndex: 0,
  1134. },
  1135. {
  1136. name: "保证功率",
  1137. type: "line",
  1138. symbol: "line", //设定为实心点
  1139. symbolSize: 0, //设定实心点的大小
  1140. smooth: true, //这个是把线变成曲线
  1141. data: chartRes.llgl,
  1142. xAxisIndex: 0,
  1143. },
  1144. {
  1145. type: "effectScatter",
  1146. showEffectOn: "emphasis",
  1147. rippleEffect: {
  1148. scale: 1,
  1149. },
  1150. name: "无用点",
  1151. symbolSize: (data) => {
  1152. return data.s ? (data.s > 10 ? 10 : data.s) : 4;
  1153. },
  1154. datasetIndex: 0,
  1155. encode: {
  1156. x: "x",
  1157. y: "y",
  1158. },
  1159. xAxisIndex: 0,
  1160. yAxisIndex: 0,
  1161. },
  1162. {
  1163. type: "effectScatter",
  1164. showEffectOn: "emphasis",
  1165. rippleEffect: {
  1166. scale: 1,
  1167. },
  1168. name: "有用点",
  1169. symbolSize: (data) => {
  1170. return data.s ? (data.s > 10 ? 10 : data.s) : 4;
  1171. },
  1172. datasetIndex: 1,
  1173. encode: {
  1174. x: "x",
  1175. y: "y",
  1176. },
  1177. xAxisIndex: 0,
  1178. yAxisIndex: 0,
  1179. },
  1180. {
  1181. name: "Cp值",
  1182. type: "line",
  1183. symbol: "line", //设定为实心点
  1184. symbolSize: 0, //设定实心点的大小
  1185. smooth: true, //这个是把线变成曲线
  1186. data: chartRes.cpz,
  1187. xAxisIndex: 0,
  1188. yAxisIndex: 1,
  1189. },
  1190. ];
  1191. combineDialog.value = true;
  1192. });
  1193. }
  1194. };
  1195. /**rateAnalysis chart */
  1196. const funText = (index) => {
  1197. let str = "";
  1198. switch (index) {
  1199. case 0:
  1200. str = "0-2.5";
  1201. break;
  1202. case 1:
  1203. str = "2.5-5";
  1204. break;
  1205. case 2:
  1206. str = "5-7.5";
  1207. break;
  1208. case 3:
  1209. str = "7.5-10";
  1210. break;
  1211. case 4:
  1212. str = "10-12.5";
  1213. break;
  1214. case 5:
  1215. str = "12.5-15";
  1216. break;
  1217. case 6:
  1218. str = "15-17.5";
  1219. break;
  1220. case 7:
  1221. str = "17.5-20";
  1222. break;
  1223. case 8:
  1224. str = "20-22.5";
  1225. break;
  1226. case 9:
  1227. str = "22.5-25";
  1228. break;
  1229. case 10:
  1230. str = "25-inf";
  1231. break;
  1232. }
  1233. return str;
  1234. };
  1235. const scatterxData = ref([
  1236. {
  1237. type: "category",
  1238. name: "度",
  1239. data: new Array(61).fill(-30).map((o, index) => Number(o + index)),
  1240. boundaryGap: false,
  1241. splitLine: {
  1242. show: true,
  1243. },
  1244. axisLine: {
  1245. show: true,
  1246. },
  1247. },
  1248. ]);
  1249. const scatteryData = ref([
  1250. {
  1251. type: "category",
  1252. data: [5, 6, 7, 8, 9, 10],
  1253. axisLine: {
  1254. show: false,
  1255. },
  1256. name: "m/s",
  1257. splitLine: {
  1258. show: false,
  1259. },
  1260. },
  1261. ]);
  1262. const scatterSeries = ref([
  1263. {
  1264. name: "对风偏航",
  1265. type: "scatter",
  1266. symbolSize: function (val) {
  1267. return val[2];
  1268. },
  1269. data: [],
  1270. markLine: {
  1271. symbol: "none",
  1272. label: {
  1273. show: false,
  1274. },
  1275. lineStyle: {
  1276. color: "#F72C5B",
  1277. width: "3",
  1278. },
  1279. data: [
  1280. {
  1281. // yAxis: powerproductionNum.value,
  1282. },
  1283. ],
  1284. },
  1285. animationDelay: function (idx) {
  1286. return idx * 5;
  1287. },
  1288. },
  1289. ]);
  1290. const chartData = ref([]); //roses的chartList
  1291. let chartId = 1;
  1292. /**submit */
  1293. const funRateSubmit = async (obj) => {
  1294. const rosesRes = await httpRequest.get("/wind/roses", {
  1295. params: {
  1296. ids: obj.processId,
  1297. mode: 0,
  1298. },
  1299. });
  1300. const lineRes = await httpRequest.get("/wind/deviation/ratio", {
  1301. params: {
  1302. ids: obj.processId,
  1303. mode: 0,
  1304. },
  1305. });
  1306. rateDialog.value = true;
  1307. if (rosesRes.code === 200) {
  1308. if (rosesRes.data.length) {
  1309. chartData.value = [];
  1310. for (const chart of rosesRes.data) {
  1311. chartData.value.push({
  1312. id: chartId,
  1313. title: "",
  1314. subtext: "风速风向玫瑰图",
  1315. xAxis: {
  1316. type: "category",
  1317. boundaryGap: false,
  1318. data: ["北", "东北", "东", "东南", "南", "西南", "西", "西北"],
  1319. splitLine: {
  1320. show: true,
  1321. },
  1322. },
  1323. isRadar: false,
  1324. series: chart.roses.length
  1325. ? chart.roses.map((o, index) => {
  1326. return {
  1327. type: "bar",
  1328. data: o,
  1329. coordinateSystem: "polar",
  1330. name: funText(index),
  1331. stack: "a",
  1332. emphasis: {
  1333. focus: "series",
  1334. },
  1335. };
  1336. })
  1337. : {
  1338. type: "bar",
  1339. data: chart.roses,
  1340. coordinateSystem: "polar",
  1341. name: "方位风速",
  1342. },
  1343. });
  1344. chartId++;
  1345. chartData.value.push({
  1346. id: chartId,
  1347. title: "",
  1348. subtext: "风速风向频次玫瑰图",
  1349. isRadar: true,
  1350. xAxis: {
  1351. type: "category",
  1352. boundaryGap: false,
  1353. data: [
  1354. "北",
  1355. "",
  1356. "东北",
  1357. "",
  1358. "东",
  1359. "",
  1360. "东南",
  1361. "",
  1362. "南",
  1363. "",
  1364. "西南",
  1365. "",
  1366. "西",
  1367. "",
  1368. "西北",
  1369. "",
  1370. ],
  1371. splitLine: {
  1372. show: true,
  1373. },
  1374. },
  1375. series: chart.roses.length
  1376. ? [
  1377. ...chart.roses.map((o, index) => {
  1378. return {
  1379. type: "bar",
  1380. data: o,
  1381. coordinateSystem: "polar",
  1382. name: funText(index),
  1383. stack: "a",
  1384. emphasis: {
  1385. focus: "series",
  1386. },
  1387. coordinateSystem: "polar",
  1388. };
  1389. }),
  1390. {
  1391. type: "radar",
  1392. tooltip: {
  1393. trigger: "item",
  1394. },
  1395. name: "对风",
  1396. data: [
  1397. {
  1398. value: chart.radar,
  1399. },
  1400. ],
  1401. },
  1402. ]
  1403. : [],
  1404. count: chart.count || [],
  1405. });
  1406. chartId++;
  1407. scatterSeries.value[0].data = chart.frequency.data.length
  1408. ? chart.frequency.data.map((item) => {
  1409. return [item[1] + "", item[0] + "", (item[2] * 15).toFixed(1)];
  1410. })
  1411. : [];
  1412. scatterSeries.value[0].markLine.data = [
  1413. {
  1414. xAxis: `${chart.frequency.avg}`,
  1415. name: `平均偏航:${chart.frequency.avg}度`,
  1416. },
  1417. ];
  1418. }
  1419. }
  1420. }
  1421. if (lineRes.code === 200) {
  1422. if (lineRes.data.length) {
  1423. lineDataSet.value[0].source = lineRes.data[0].scatter.map((o) => {
  1424. return [o.x + "", o.y];
  1425. });
  1426. const lineSeriseMax = Math.max(...lineRes.data[0].count);
  1427. const lineSeriseMaxIndex = lineRes.data[0].count.indexOf(lineSeriseMax);
  1428. lineSeries.value = [
  1429. {
  1430. name: "对风频次",
  1431. type: "line",
  1432. symbol: "line", //设定为实心点
  1433. symbolSize: 0, //设定实心点的大小
  1434. smooth: true, //这个是把线变成曲线
  1435. data: lineRes.data[0].count,
  1436. yAxisIndex: 1,
  1437. markLine: {
  1438. symbol: "none",
  1439. label: {
  1440. show: false,
  1441. },
  1442. lineStyle: {
  1443. color: "#F72C5B",
  1444. width: "3",
  1445. },
  1446. large: true,
  1447. data: [
  1448. {
  1449. // name: `平均偏航:${chart.frequency.avg}度`,
  1450. xAxis: lineSeriseMaxIndex,
  1451. },
  1452. ],
  1453. },
  1454. },
  1455. {
  1456. type: "effectScatter",
  1457. showEffectOn: "emphasis",
  1458. rippleEffect: {
  1459. scale: 1,
  1460. },
  1461. legendHoverLink: false,
  1462. name: "数据散点",
  1463. symbolSize: 5,
  1464. datasetIndex: 0,
  1465. encode: {
  1466. x: "x",
  1467. y: "y",
  1468. },
  1469. yAxisIndex: 0,
  1470. },
  1471. ];
  1472. }
  1473. }
  1474. };
  1475. /**lineChart */
  1476. const linexAxis = ref({
  1477. type: "category",
  1478. data: new Array(101)
  1479. .fill(-50)
  1480. .map((o, index) => Number((o + index).toFixed(1))),
  1481. splitLine: {
  1482. show: false,
  1483. },
  1484. axisTick: {
  1485. show: true,
  1486. },
  1487. });
  1488. const lineyAxis = ref([
  1489. {
  1490. type: "value",
  1491. name: "m/s",
  1492. splitLine: {
  1493. show: false,
  1494. },
  1495. axisTick: {
  1496. show: true,
  1497. },
  1498. },
  1499. {
  1500. type: "value",
  1501. name: "频次",
  1502. splitLine: {
  1503. show: false,
  1504. },
  1505. axisTick: {
  1506. show: true,
  1507. },
  1508. },
  1509. ]);
  1510. const lineSeries = ref([]);
  1511. const lineDataSet = ref([
  1512. {
  1513. source: [],
  1514. },
  1515. ]);
  1516. /** rate dialog */
  1517. const rateDialog = ref(false);
  1518. const dbRateDialog = ref(false);
  1519. const actChartName = ref("");
  1520. const actDiaTitle = ref("");
  1521. const diaPanelRef = ref();
  1522. const exportLoading = ref(false);
  1523. const actCopList = ref([
  1524. // {
  1525. // xAxis: [],
  1526. // subtext: '',
  1527. // title: '',
  1528. // isRadar: false,
  1529. // series: [],
  1530. // yAxis: [],
  1531. // dataset: []
  1532. // }
  1533. ]);
  1534. // 作为actCopList的备份 在actCopList赋值多个时 同时赋值, 在dialog弹出时清空. 作用: 在actCopList变化时, 重新赋值原始数据
  1535. const actCopListBak = ref([]);
  1536. const checkAll = ref(true);
  1537. const queryForm = reactive({
  1538. checkIds: [],
  1539. });
  1540. const funCheckAll = () => {
  1541. checkAll.value = !checkAll.value;
  1542. if (checkAll.value) {
  1543. queryForm.checkIds = windList.value.map((o) => o.processId);
  1544. } else {
  1545. queryForm.checkIds = [];
  1546. }
  1547. };
  1548. const funActCop = (obj, type) => {
  1549. switch (type) {
  1550. case "chartCop1":
  1551. actChartName.value = "chartCop1";
  1552. obj.actCop = shallowRef(chartCop);
  1553. actDiaTitle.value = "风速风向玫瑰图";
  1554. break;
  1555. case "chartCop2":
  1556. actChartName.value = "chartCop2";
  1557. obj.actCop = shallowRef(chartCop);
  1558. actDiaTitle.value = "风速风向频次玫瑰图";
  1559. break;
  1560. case "lineChartCop":
  1561. actChartName.value = "lineChartCop";
  1562. obj.actCop = shallowRef(lineChartCop);
  1563. actDiaTitle.value = "对风偏差分析图";
  1564. break;
  1565. case "scatterSingleChartCop":
  1566. actChartName.value = "scatterSingleChartCop";
  1567. obj.actCop = shallowRef(scatterSingleChartCop);
  1568. actDiaTitle.value = "静态偏航对风分析图";
  1569. break;
  1570. }
  1571. obj.isBrush = type === "lineChartCop" ? false : false;
  1572. obj.id = chartId;
  1573. chartId++;
  1574. dbRateDialog.value = true;
  1575. actCopListBak.value = [];
  1576. nextTick(() => {
  1577. actCopList.value = [obj];
  1578. });
  1579. };
  1580. const funDiaSubmit = async () => {
  1581. let url = "";
  1582. switch (actChartName.value) {
  1583. case "chartCop1":
  1584. url = "/wind/roses";
  1585. break;
  1586. case "chartCop2":
  1587. url = "/wind/roses";
  1588. break;
  1589. case "lineChartCop":
  1590. url = "/wind/deviation/ratio";
  1591. break;
  1592. case "scatterSingleChartCop":
  1593. url = "/wind/roses";
  1594. break;
  1595. }
  1596. if (url) {
  1597. const res = await httpRequest.get(url, {
  1598. params: {
  1599. ids: queryForm.checkIds.join(","),
  1600. mode: 0,
  1601. },
  1602. });
  1603. if (res.code === 200) {
  1604. actCopList.value = [];
  1605. actCopListBak.value = []; //清空备份
  1606. if (res.data.length) {
  1607. for (const chart of res.data) {
  1608. if (actChartName.value === "chartCop1") {
  1609. actCopList.value.push({
  1610. id: chartId,
  1611. isBrush: false,
  1612. actCop: shallowRef(chartCop),
  1613. title: chart.wt,
  1614. subtext: "风速风向玫瑰图",
  1615. xAxis: {
  1616. type: "category",
  1617. boundaryGap: false,
  1618. data: [
  1619. "北",
  1620. "",
  1621. "东北",
  1622. "",
  1623. "东",
  1624. "",
  1625. "东南",
  1626. "",
  1627. "南",
  1628. "",
  1629. "西南",
  1630. "",
  1631. "西",
  1632. "",
  1633. "西北",
  1634. "",
  1635. ],
  1636. splitLine: {
  1637. show: true,
  1638. },
  1639. },
  1640. isRadar: false,
  1641. series: {
  1642. type: "bar",
  1643. data: chart.roses,
  1644. coordinateSystem: "polar",
  1645. name: "方位风速",
  1646. },
  1647. count: chart.ys || [],
  1648. });
  1649. chartId++;
  1650. }
  1651. if (actChartName.value === "chartCop2") {
  1652. actCopList.value.push({
  1653. id: chartId,
  1654. isBrush: false,
  1655. actCop: shallowRef(chartCop),
  1656. title: chart.wt,
  1657. subtext: "风速风向频次玫瑰图",
  1658. xAxis: {
  1659. type: "category",
  1660. boundaryGap: false,
  1661. data: [
  1662. "北",
  1663. "",
  1664. "东北",
  1665. "",
  1666. "东",
  1667. "",
  1668. "东南",
  1669. "",
  1670. "南",
  1671. "",
  1672. "西南",
  1673. "",
  1674. "西",
  1675. "",
  1676. "西北",
  1677. "",
  1678. ],
  1679. splitLine: {
  1680. show: true,
  1681. },
  1682. },
  1683. isRadar: true,
  1684. series: chart.roses.length
  1685. ? [
  1686. ...chart.roses.map((o, index) => {
  1687. return {
  1688. type: "bar",
  1689. data: o,
  1690. coordinateSystem: "polar",
  1691. name: funText(index),
  1692. stack: "a",
  1693. emphasis: {
  1694. focus: "series",
  1695. },
  1696. coordinateSystem: "polar",
  1697. };
  1698. }),
  1699. {
  1700. type: "radar",
  1701. tooltip: {
  1702. trigger: "item",
  1703. },
  1704. name: "对风",
  1705. data: [
  1706. {
  1707. value: chart.radar,
  1708. },
  1709. ],
  1710. },
  1711. ]
  1712. : [],
  1713. count: chart.count || [],
  1714. });
  1715. chartId++;
  1716. }
  1717. if (actChartName.value === "lineChartCop") {
  1718. actCopList.value.push({
  1719. id: chartId,
  1720. isBrush: false,
  1721. actCop: shallowRef(lineChartCop),
  1722. title: chart.wtId,
  1723. subtext: "对风偏差分析图",
  1724. xAxis: linexAxis.value,
  1725. yAxis: lineyAxis.value,
  1726. dataset: [
  1727. {
  1728. source: chart.scatter.map((o) => {
  1729. return [o.x + "", o.y];
  1730. }),
  1731. },
  1732. ],
  1733. isRadar: false,
  1734. series: [
  1735. {
  1736. name: "对风频次",
  1737. type: "line",
  1738. symbol: "line", //设定为实心点
  1739. symbolSize: 0, //设定实心点的大小
  1740. smooth: true, //这个是把线变成曲线
  1741. data: chart.count,
  1742. yAxisIndex: 1,
  1743. },
  1744. {
  1745. type: "effectScatter",
  1746. showEffectOn: "emphasis",
  1747. rippleEffect: {
  1748. scale: 1,
  1749. },
  1750. legendHoverLink: false,
  1751. name: "数据散点",
  1752. symbolSize: 5,
  1753. datasetIndex: 0,
  1754. encode: {
  1755. x: "x",
  1756. y: "y",
  1757. },
  1758. yAxisIndex: 0,
  1759. },
  1760. ],
  1761. });
  1762. chartId++;
  1763. }
  1764. if (actChartName.value === "scatterSingleChartCop") {
  1765. actCopList.value.push({
  1766. id: chartId,
  1767. isBrush: false,
  1768. actCop: shallowRef(scatterSingleChartCop),
  1769. title: chart.wt,
  1770. subtext: "静态偏航对风分析图",
  1771. xAxis: scatterxData.value,
  1772. yAxis: scatteryData.value,
  1773. isRadar: false,
  1774. series: [
  1775. {
  1776. name: "对风偏航",
  1777. type: "scatter",
  1778. symbolSize: function (val) {
  1779. return val[2];
  1780. },
  1781. markLine: {
  1782. symbol: "none",
  1783. label: {
  1784. show: false,
  1785. },
  1786. lineStyle: {
  1787. color: "#F72C5B",
  1788. width: "3",
  1789. },
  1790. data: [
  1791. {
  1792. name: `平均偏航:${chart.frequency.avg}度`,
  1793. xAxis: `${chart.frequency.avg}`,
  1794. },
  1795. ],
  1796. },
  1797. data: chart.frequency.data.length
  1798. ? chart.frequency.data.map((item) => {
  1799. return [
  1800. item[1] + "",
  1801. item[0] + "",
  1802. (item[2] * 15).toFixed(1),
  1803. ];
  1804. })
  1805. : [],
  1806. animationDelay: function (idx) {
  1807. return idx * 5;
  1808. },
  1809. },
  1810. ],
  1811. });
  1812. chartId++;
  1813. }
  1814. }
  1815. actCopListBak.value = actCopList.value;
  1816. }
  1817. }
  1818. }
  1819. };
  1820. const funDiaExport = () => {
  1821. exportLoading.value = true;
  1822. tools.scrollToPDF(diaPanelRef.value, actDiaTitle.value, () => {
  1823. exportLoading.value = false;
  1824. });
  1825. };
  1826. const funDbClick = (obj) => {
  1827. if (actCopListBak.value.length > 1) {
  1828. //判断大于1时, 才有双击放大功能
  1829. if (actCopList.value.length === 1) {
  1830. actCopList.value = actCopListBak.value;
  1831. } else {
  1832. actCopList.value = [obj];
  1833. }
  1834. }
  1835. };
  1836. const theme = ref(null);
  1837. const echartsTheme = ref("");
  1838. watch(
  1839. () => store.state.theme,
  1840. (newVal, oldVal) => {
  1841. theme.value = newVal;
  1842. echartsTheme.value = !newVal ? "dark" : "";
  1843. funGetTree();
  1844. },
  1845. {
  1846. deep: true,
  1847. }
  1848. );
  1849. const getOnline = () => {
  1850. axios({
  1851. method: "get",
  1852. baseURL: "ping",
  1853. url: "",
  1854. })
  1855. .then((res) => {
  1856. showOnlineMap.value = true;
  1857. })
  1858. .catch((e) => {
  1859. showOnlineMap.value = false;
  1860. });
  1861. };
  1862. const initPageData = () => {
  1863. actTreeNode.value = null;
  1864. treeData.value = funRepeatMap(JSON.parse(JSON.stringify(jsonData.treeData)));
  1865. excelList.value = [];
  1866. if (actTreeNode.value) {
  1867. if (actTreeNode.value.childs) {
  1868. excelList.value = actTreeNode.value.childs.map((o) => {
  1869. return {
  1870. id: o.id,
  1871. interval: o.interval,
  1872. path: o.path,
  1873. prepareid: o.prepareid,
  1874. station: o.station,
  1875. time: o.time,
  1876. type: o.type,
  1877. windturbine: o.windturbine,
  1878. isCheck: false,
  1879. name: o.path.substring(
  1880. o.path.indexOf(o.station + "_") + (o.station + "_").length
  1881. ),
  1882. };
  1883. });
  1884. } else {
  1885. excelList.value = [];
  1886. }
  1887. if (treeCopRef.value) {
  1888. treeCopRef.value.$refs.tree.setCheckedKeys([actTreeNode.value.id]);
  1889. excelCheckIds.value = actTreeNode.value.childs.map((o) => o.id);
  1890. let windList = [];
  1891. jsonData.locationData.forEach((ele) => {
  1892. if (ele.longitude && ele.latitude) {
  1893. windList.push(ele);
  1894. }
  1895. });
  1896. windList.value = windList;
  1897. }
  1898. }
  1899. };
  1900. /**mounted */
  1901. onMounted(() => {
  1902. // getOnline();
  1903. initPageData();
  1904. funGetTree();
  1905. theme.value = store.state.theme;
  1906. echartsTheme.value = !theme.value ? "dark" : "";
  1907. tableHeight.value = window.innerHeight - 115 + "px";
  1908. excelHeight.value = window.innerHeight - 115 + "px";
  1909. treeHeight.value = window.innerHeight - 115 + "px";
  1910. window.addEventListener("resize", () => {
  1911. tableHeight.value = window.innerHeight - 115 + "px";
  1912. excelHeight.value = window.innerHeight - 115 + "px";
  1913. treeHeight.value = window.innerHeight - 115 + "px";
  1914. });
  1915. /**test */
  1916. // funExcelChange({
  1917. // id: 1,
  1918. // name: 'excel',
  1919. // type: 'fitting',
  1920. // })
  1921. });
  1922. /**activated */
  1923. // onActivated(() => {
  1924. // funGetTree()
  1925. // })
  1926. const funMapDone = (mapStatus) => {
  1927. if (mapStatus) {
  1928. funGetTree();
  1929. }
  1930. };
  1931. </script>
  1932. <style lang="less" scoped>
  1933. .dataAnalysisPosAnal {
  1934. height: 100%;
  1935. .dataAnalysisPosAnalMain {
  1936. height: 100%;
  1937. .main_top {
  1938. height: 40px;
  1939. display: flex;
  1940. align-items: center;
  1941. .topPsty {
  1942. position: relative;
  1943. top: 5px;
  1944. padding: 7px 20px;
  1945. font-size: 12px;
  1946. font-weight: 600;
  1947. margin-left: 10px;
  1948. border-radius: 3px;
  1949. }
  1950. }
  1951. .main {
  1952. display: flex;
  1953. width: 100%;
  1954. .treeDataMain,
  1955. .excelDataMain,
  1956. .tableDataMain {
  1957. border-radius: 10px;
  1958. }
  1959. .treeDataMain {
  1960. margin-right: 10px;
  1961. padding: 10px 0 10px 10px;
  1962. width: calc(19% - 20px);
  1963. }
  1964. .excelDataMain {
  1965. margin-right: 10px;
  1966. padding: 10px 0 10px 10px;
  1967. width: calc(15% - 20px);
  1968. .excelDataMain_top {
  1969. height: 49%;
  1970. padding: 5px 0;
  1971. }
  1972. .excelDataMain_bot {
  1973. padding: 5px 0;
  1974. }
  1975. }
  1976. .tableDataMain {
  1977. padding: 10px;
  1978. width: calc(66% - 20px);
  1979. position: relative;
  1980. .butten_com {
  1981. position: absolute;
  1982. right: 20px;
  1983. z-index: 111111;
  1984. }
  1985. }
  1986. }
  1987. }
  1988. }
  1989. .rightMenuDialog {
  1990. .el-overlay-dialog {
  1991. overflow: hidden;
  1992. }
  1993. }
  1994. .themeDark {
  1995. .dataAnalysisPosAnalMain {
  1996. .main_top {
  1997. .topPsty {
  1998. color: #1c99ff;
  1999. background: #1e2126;
  2000. }
  2001. }
  2002. .main {
  2003. background: #13171e;
  2004. .treeDataMain {
  2005. background: transparent;
  2006. }
  2007. .excelDataMain {
  2008. background: #313233;
  2009. }
  2010. .tableDataMain {
  2011. margin-top: 5px;
  2012. background: #212223;
  2013. }
  2014. }
  2015. }
  2016. }
  2017. .themeLight {
  2018. padding: 0;
  2019. .dataAnalysisPosAnalMain {
  2020. .main_top {
  2021. .topPsty {
  2022. color: #2778ff;
  2023. background: #ffffff;
  2024. }
  2025. }
  2026. .main {
  2027. background: #e6e8f2;
  2028. .treeDataMain {
  2029. background: transparent;
  2030. }
  2031. .excelDataMain {
  2032. background: #f4f6fb;
  2033. }
  2034. .tableDataMain {
  2035. background: #fff;
  2036. margin-top: 5px;
  2037. }
  2038. }
  2039. }
  2040. }
  2041. </style>