index.vue 72 KB

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