index.vue 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. <template>
  2. <div class="dataAnalysisLineAna" :class="!theme ? 'themeDark' : 'themeLight'">
  3. <div class="dataAnalysisLineAnaMain">
  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="px-[10px] shadow rounded-[6px] shadow-blue-500">
  33. <SubmitBtn
  34. class="absolute right-[196px] top-[6px] z-10"
  35. desc="区域划分"
  36. @click="funChartArea"
  37. >
  38. </SubmitBtn>
  39. <SubmitBtn
  40. class="absolute right-[106px] top-[6px] z-10"
  41. desc="时间占比"
  42. @click="funTimeArea"
  43. >
  44. </SubmitBtn>
  45. <SubmitBtn
  46. class="absolute right-[16px] top-[6px] z-10"
  47. desc="额定功率"
  48. @click="funPower"
  49. >
  50. </SubmitBtn>
  51. <div
  52. :style="{
  53. height:
  54. typeof tableHeight === 'string'
  55. ? tableHeight
  56. : tableHeight + 'px',
  57. overflow: 'hidden',
  58. }"
  59. class="p-[10px]"
  60. >
  61. <CurrentScatterChart
  62. ref="chartRef"
  63. width="100%"
  64. :height="`calc( ${tableHeight} - 40px )`"
  65. chartTitle=""
  66. :xAxisData="xAxisData"
  67. :yAxisData="{ splitLine: { show: false } }"
  68. :seriesData="seriesData"
  69. :showLegend="true"
  70. :brushSelected="!isChartArea"
  71. :dataSet="dataSet"
  72. @getSelected="funChartSelect"
  73. :theme="theme"
  74. :echartsTheme="echartsTheme"
  75. />
  76. </div>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. <el-dialog
  82. custom-class="windLifeDialog"
  83. draggable
  84. width="1000px"
  85. v-model="tmDialog"
  86. title="时间占比"
  87. >
  88. <el-tabs v-model="activeTab">
  89. <el-tab-pane label="运行时间" name="1"> </el-tab-pane>
  90. <el-tab-pane label="不运行时间" name="2"></el-tab-pane>
  91. <div v-if="activeTab === '1'">
  92. <bar-chart-cop
  93. height="600px"
  94. width="100%"
  95. :xAxis="barxAxis"
  96. :yAxis="baryAxis"
  97. :series="barSeries"
  98. >
  99. </bar-chart-cop>
  100. </div>
  101. <div v-if="activeTab === '2'">
  102. <!-- :colors="[color: ["#05bb4c", "#C531C7", "#4b55ae", "#fa8c16", "#1DA0D7", "#DD5044"],
  103. 'rgb(222,132,82)',
  104. 'rgb(105,188,80)',
  105. 'rgb(197,78,82)',
  106. 'rgb(129,114,181)',
  107. ]" -->
  108. <bar-chart-cop
  109. height="600px"
  110. :colors="['#05bb4c', '#C531C7', '#4b55ae', '#fa8c16', '#1DA0D7', '#DD5044', '#323E6F']"
  111. width="100%"
  112. :xAxis="barxAxis"
  113. :yAxis="baryAxis"
  114. :series="barUnWorkSeries"
  115. ></bar-chart-cop>
  116. </div>
  117. </el-tabs>
  118. </el-dialog>
  119. <el-dialog
  120. custom-class="windLifeDialog"
  121. draggable
  122. width="1000px"
  123. v-model="powerDialog"
  124. title="额定功率"
  125. >
  126. <bar-chart-cop
  127. height="350px"
  128. :colors="[]"
  129. width="100%"
  130. :xAxis="powerxAxis"
  131. :yAxis="countyAxis"
  132. :theme="theme"
  133. :echartsTheme="echartsTheme"
  134. :series="countSeries"
  135. ></bar-chart-cop>
  136. <bar-chart-cop
  137. height="350px"
  138. :colors="[]"
  139. width="100%"
  140. :xAxis="powerxAxis"
  141. :yAxis="poweryAxis"
  142. :theme="theme"
  143. :echartsTheme="echartsTheme"
  144. :series="powerSeries"
  145. ></bar-chart-cop>
  146. </el-dialog>
  147. <el-dialog
  148. custom-class="windLifeDialog warn-table"
  149. draggable
  150. v-model="wtDialog"
  151. title="曲线偏差率"
  152. >
  153. <el-table :data="wtData" row-key="id" :max-height="600">
  154. <el-table-column property="code" align="center" label="风机" />
  155. <el-table-column
  156. property="pc5ratio"
  157. sortable
  158. align="center"
  159. label="3~5m"
  160. />
  161. <el-table-column
  162. property="pc7ratio"
  163. sortable
  164. align="center"
  165. label="5~7m"
  166. />
  167. <el-table-column
  168. property="pc9ratio"
  169. sortable
  170. align="center"
  171. label="7~9m"
  172. />
  173. <el-table-column
  174. property="pc11ratio"
  175. sortable
  176. align="center"
  177. label="9~11m"
  178. />
  179. <el-table-column
  180. property="pc20ratio"
  181. sortable
  182. align="center"
  183. label="11~20m"
  184. />
  185. <el-table-column
  186. property="pc25ratio"
  187. sortable
  188. align="center"
  189. label="20~25m"
  190. />
  191. <el-table-column
  192. property="pcratio"
  193. sortable
  194. align="center"
  195. label="3~25m"
  196. />
  197. </el-table>
  198. </el-dialog>
  199. </div>
  200. </template>
  201. <script setup name="prepare">
  202. import excelCop from "@/components/generatingCapacityComponent/excel.vue";
  203. import treeCop from "@/components/generatingCapacityComponent/tree.vue";
  204. import barChartCop from "./components/barChart.vue";
  205. import SubmitBtn from "@/components/generatingCapacityComponent/SubmitBtn.vue";
  206. import { ref, nextTick, onActivated, onMounted, reactive, watch } from "vue";
  207. import { useStore } from "vuex";
  208. import httpRequest from "@/utils/request.js";
  209. import { ElMessage } from "element-plus";
  210. import util from "@tools/util";
  211. import CurrentScatterChart from "./components/current-scatter-chart.vue";
  212. import jsonData from "./components/data.json";
  213. // import dotRes from '@/data/dot.json'
  214. // import tableRes from '@/data/table.json'
  215. // import areaDataRes from '@/data/areaData.json'
  216. /**配置参数 */
  217. const treeHeight = ref(window.innerHeight - 140 + "px"); //tree高度
  218. const excelHeight = ref(window.innerHeight - 140 + "px"); //excel高度
  219. const tableHeight = ref(window.innerHeight - 140 + "px");
  220. /**excel 开始 */
  221. const excelCheckboxShow = ref(false);
  222. const excelCheckIds = ref([]);
  223. const excelList = ref([]);
  224. const funExcelChange = async (obj) => {
  225. //点击excel项时
  226. return false;
  227. };
  228. const funExcelCheckChange = ({ checkArr, data }) => {
  229. //bug
  230. excelCheckIds.value = checkArr;
  231. funSubmit();
  232. };
  233. /**prepare tree 开始 */
  234. const treeData = ref([]);
  235. const treeCopRef = ref(); //treeCop ref
  236. const actTreeNode = ref(null); //当前激活的treeNode
  237. const funRepeatMap = (arr, type = "fitting") => {
  238. return arr.map((o) => {
  239. if (o.children) {
  240. const findIndex = o.children.findIndex((p) => !!p.type);
  241. if (findIndex !== -1) {
  242. o.childs = o.children;
  243. o.children = [];
  244. if (!actTreeNode.value && type === "fitting") {
  245. //判断当且仅有process获取tree时 赋值
  246. actTreeNode.value = o;
  247. }
  248. }
  249. }
  250. return {
  251. ...o,
  252. children: o.children ? funRepeatMap(o.children, type) : [],
  253. };
  254. });
  255. };
  256. const funGetTree = async () => {
  257. actTreeNode.value = null;
  258. const res = await httpRequest.get("/power/fitting/tree");
  259. treeData.value = funRepeatMap(res.data);
  260. excelList.value = [];
  261. nextTick(() => {
  262. if (actTreeNode.value) {
  263. funCurrentChange({
  264. current: actTreeNode.value,
  265. currentNode: null,
  266. });
  267. if (treeCopRef.value && treeCopRef.value.data) {
  268. treeCopRef.value.$refs.tree.setCheckedKeys(
  269. [actTreeNode.value.id],
  270. true
  271. );
  272. // excelCheckIds.value = actTreeNode.value.childs.map(o => o.id)
  273. excelCheckIds.value = [actTreeNode.value.childs[0].id];
  274. funSubmit();
  275. }
  276. }
  277. });
  278. };
  279. const funCurrentChange = ({ current, currentNode }) => {
  280. excelCheckboxShow.value = true;
  281. if (current.childs) {
  282. excelList.value = current.childs.map((o) => {
  283. return {
  284. id: o.id,
  285. interval: o.interval,
  286. path: o.path,
  287. prepareid: o.prepareid,
  288. station: o.station,
  289. time: o.time,
  290. type: o.type,
  291. windturbine: o.windturbine,
  292. name: o.path.substring(
  293. o.path.indexOf(o.station + "_") + (o.station + "_").length
  294. ),
  295. };
  296. });
  297. } else {
  298. excelList.value = [];
  299. }
  300. };
  301. const funTreeCheckChange = ({
  302. current,
  303. checkedNodes,
  304. checkedKeys,
  305. halfCheckedNodes,
  306. halfCheckedKeys,
  307. }) => {
  308. //tree change -> excel change
  309. funCurrentChange({
  310. current,
  311. currentNode: "",
  312. });
  313. const checkIds = [];
  314. if (checkedNodes.checkedNodes.length) {
  315. for (const node of checkedNodes.checkedNodes) {
  316. if (node.childs && node.childs.length) {
  317. for (const child of node.childs) {
  318. checkIds.push(child.id);
  319. }
  320. }
  321. }
  322. }
  323. // if (checkedNodes) {
  324. // let checkArr = [checkedNodes]
  325. // checkArr.forEach(it => {
  326. // if (it.childs && it.childs.length) {
  327. // it.childs.forEach(iv => {
  328. // checkIds.push(iv.id)
  329. // })
  330. // }
  331. // })
  332. // }
  333. excelCheckIds.value = checkIds;
  334. funSubmit();
  335. };
  336. /**search 开始 */
  337. const funSubmit = async () => {
  338. if (!excelCheckIds.value.length) {
  339. ElMessage.error("请勾选要执行的项");
  340. return false;
  341. }
  342. wtData.value = [];
  343. const params = {
  344. ids: excelCheckIds.value.join(","),
  345. };
  346. const res = await httpRequest.get("/power/fitting/line", {
  347. params: params,
  348. });
  349. if (res.code === 200) {
  350. seriesData.value = [];
  351. if (res.data.bzgl) {
  352. seriesData.value.push({
  353. name: "保证功率",
  354. type: "line",
  355. symbol: "line", //设定为实心点
  356. symbolSize: 0, //设定实心点的大小
  357. smooth: true, //这个是把线变成曲线
  358. data: res.data.bzgl || [],
  359. xAxisIndex: 0,
  360. });
  361. }
  362. if (res.data.sjgl.length) {
  363. for (const wtObj of res.data.sjgl) {
  364. seriesData.value.push({
  365. // name: wtObj.obj.windturbineId + "\n实际功率",
  366. name: wtObj.obj.code + "\n实际功率",
  367. type: "line",
  368. symbol: "line", //设定为实心点
  369. symbolSize: 0, //设定实心点的大小
  370. smooth: true, //这个是把线变成曲线
  371. data: wtObj.sjgl || [],
  372. xAxisIndex: 0,
  373. });
  374. wtData.value.push(wtObj.obj);
  375. }
  376. }
  377. }
  378. };
  379. /**chart Data */
  380. const avgObj = reactive({
  381. //平均cpz等
  382. cpavg: "",
  383. frequency: "",
  384. pcratio: "",
  385. });
  386. const xAxisData = ref([]);
  387. const chartRef = ref(); //chart 的ref
  388. const seriesData = ref([]);
  389. const isChartArea = ref(false); // 用来控制图表是否区域划分
  390. const dataSet = ref("");
  391. const funChartSelect = async (batch) => {
  392. return false;
  393. };
  394. const funChartArea = () => {
  395. if (seriesData.value.length) {
  396. // 获取数据后 展示dialog table 数据
  397. wtDialog.value = true;
  398. if (!isChartArea.value) {
  399. // 请求一下
  400. seriesData.value[0] = {
  401. ...seriesData.value[0],
  402. markLine: {
  403. symbol: "none",
  404. label: {
  405. show: false,
  406. },
  407. lineStyle: {
  408. color: "rgba(96,174,255, 1)",
  409. },
  410. data: [
  411. {
  412. xAxis: 3,
  413. valueIndex: 0,
  414. },
  415. {
  416. xAxis: 5,
  417. valueIndex: 0,
  418. },
  419. {
  420. xAxis: 7,
  421. valueIndex: 0,
  422. },
  423. {
  424. xAxis: 9,
  425. valueIndex: 0,
  426. },
  427. {
  428. xAxis: 11,
  429. valueIndex: 0,
  430. },
  431. {
  432. xAxis: 20,
  433. valueIndex: 0,
  434. },
  435. {
  436. xAxis: 25,
  437. valueIndex: 0,
  438. },
  439. ],
  440. },
  441. markArea: {
  442. label: {
  443. fontSize: util.vh(12),
  444. },
  445. itemStyle: {
  446. color: "rgba(236,245,255, 0)",
  447. },
  448. emphasis: {
  449. itemStyle: {
  450. color: "rgba(96,174,255, 0.5)",
  451. },
  452. },
  453. data: [
  454. [
  455. {
  456. name: `3~5m`,
  457. xAxis: 3,
  458. },
  459. {
  460. xAxis: 5,
  461. },
  462. ],
  463. [
  464. {
  465. name: `5~7m`,
  466. xAxis: 5,
  467. },
  468. {
  469. xAxis: 7,
  470. },
  471. ],
  472. [
  473. {
  474. name: `7~9m`,
  475. xAxis: 7,
  476. },
  477. {
  478. xAxis: 9,
  479. },
  480. ],
  481. [
  482. {
  483. name: `9~11m`,
  484. xAxis: 9,
  485. },
  486. {
  487. xAxis: 11,
  488. },
  489. ],
  490. [
  491. {
  492. name: `11~20m`,
  493. xAxis: 11,
  494. },
  495. {
  496. xAxis: 20,
  497. },
  498. ],
  499. [
  500. {
  501. name: `20~25m`,
  502. xAxis: 20,
  503. },
  504. {
  505. xAxis: 25,
  506. },
  507. ],
  508. ],
  509. },
  510. };
  511. isChartArea.value = true;
  512. } else {
  513. seriesData.value[0] = {
  514. ...seriesData.value[0],
  515. markLine: null,
  516. markArea: null,
  517. };
  518. isChartArea.value = false;
  519. }
  520. }
  521. };
  522. /**tmdialog 数据 */
  523. const tmDialog = ref(false);
  524. const barxAxis = reactive({
  525. type: "category",
  526. data: [],
  527. splitLine: {
  528. show: false,
  529. },
  530. axisTick: {
  531. show: true,
  532. },
  533. });
  534. const baryAxis = ref({
  535. type: "value",
  536. name: "小时",
  537. splitLine: {
  538. show: false,
  539. },
  540. axisTick: {
  541. show: true,
  542. },
  543. });
  544. const barSeries = ref([
  545. {
  546. name: "不运行",
  547. type: "bar",
  548. stack: "a",
  549. data: [],
  550. },
  551. {
  552. name: "3~5m风速",
  553. type: "bar",
  554. stack: "a",
  555. data: [],
  556. },
  557. {
  558. name: "5~10m风速",
  559. type: "bar",
  560. stack: "a",
  561. data: [],
  562. },
  563. {
  564. name: "10~12m风速",
  565. type: "bar",
  566. stack: "a",
  567. data: [],
  568. },
  569. {
  570. name: "12~25m风速",
  571. type: "bar",
  572. stack: "a",
  573. data: [],
  574. },
  575. ]);
  576. const barUnWorkSeries = ref([
  577. {
  578. name: "3~5m风速",
  579. type: "bar",
  580. stack: "a",
  581. data: [],
  582. },
  583. {
  584. name: "5~10m风速",
  585. type: "bar",
  586. stack: "a",
  587. data: [],
  588. },
  589. {
  590. name: "10~12m风速",
  591. type: "bar",
  592. stack: "a",
  593. data: [],
  594. },
  595. {
  596. name: "12~25m风速",
  597. type: "bar",
  598. stack: "a",
  599. data: [],
  600. },
  601. ]);
  602. const funTimeArea = () => {
  603. if (seriesData.value.length) {
  604. activeTab.value = "1";
  605. //获取数据
  606. const res = httpRequest
  607. .get("/power/fitting/time", {
  608. params: {
  609. ids: excelCheckIds.value.join(","),
  610. },
  611. })
  612. .then((res) => {
  613. if (res.code === 200) {
  614. barxAxis.data = [];
  615. barSeries.value = [
  616. {
  617. name: "不运行",
  618. type: "bar",
  619. stack: "a",
  620. data: [],
  621. },
  622. {
  623. name: "3~5m风速",
  624. type: "bar",
  625. stack: "a",
  626. data: [],
  627. },
  628. {
  629. name: "5~7m风速",
  630. type: "bar",
  631. stack: "a",
  632. data: [],
  633. },
  634. {
  635. name: "7~9m风速",
  636. type: "bar",
  637. stack: "a",
  638. data: [],
  639. },
  640. {
  641. name: "9~11m风速",
  642. type: "bar",
  643. stack: "a",
  644. data: [],
  645. },
  646. {
  647. name: "11~20m风速",
  648. type: "bar",
  649. stack: "a",
  650. data: [],
  651. },
  652. {
  653. name: "20~25m风速",
  654. type: "bar",
  655. stack: "a",
  656. data: [],
  657. },
  658. ];
  659. barUnWorkSeries.value = [
  660. {
  661. name: "3~5m风速",
  662. type: "bar",
  663. stack: "a",
  664. data: [],
  665. },
  666. {
  667. name: "5~7m风速",
  668. type: "bar",
  669. stack: "a",
  670. data: [],
  671. },
  672. {
  673. name: "7~9m风速",
  674. type: "bar",
  675. stack: "a",
  676. data: [],
  677. },
  678. {
  679. name: "9~11m风速",
  680. type: "bar",
  681. stack: "a",
  682. data: [],
  683. },
  684. {
  685. name: "11~20m风速",
  686. type: "bar",
  687. stack: "a",
  688. data: [],
  689. },
  690. {
  691. name: "20~25m风速",
  692. type: "bar",
  693. stack: "a",
  694. data: [],
  695. },
  696. ];
  697. for (const wtObj of res.data) {
  698. barxAxis.data.push(wtObj.wtId);
  699. for (const timeKey in wtObj.time1) {
  700. barSeries.value[timeKey].data.push(
  701. (wtObj.time1[timeKey] / 60).toFixed(0)
  702. );
  703. }
  704. for (const time2Key in wtObj.time2) {
  705. barUnWorkSeries.value[time2Key].data.push(
  706. (wtObj.time2[time2Key] / 60).toFixed(0)
  707. );
  708. }
  709. }
  710. tmDialog.value = true;
  711. }
  712. })
  713. .catch(() => {
  714. barxAxis.data = [];
  715. barSeries.value = [
  716. {
  717. name: "不运行",
  718. type: "bar",
  719. stack: "a",
  720. data: [],
  721. },
  722. {
  723. name: "3~5m风速",
  724. type: "bar",
  725. stack: "a",
  726. data: [],
  727. },
  728. {
  729. name: "5~7m风速",
  730. type: "bar",
  731. stack: "a",
  732. data: [],
  733. },
  734. {
  735. name: "7~9m风速",
  736. type: "bar",
  737. stack: "a",
  738. data: [],
  739. },
  740. {
  741. name: "9~11m风速",
  742. type: "bar",
  743. stack: "a",
  744. data: [],
  745. },
  746. {
  747. name: "11~20m风速",
  748. type: "bar",
  749. stack: "a",
  750. data: [],
  751. },
  752. {
  753. name: "20~25m风速",
  754. type: "bar",
  755. stack: "a",
  756. data: [],
  757. },
  758. ];
  759. barUnWorkSeries.value = [
  760. {
  761. name: "3~5m风速",
  762. type: "bar",
  763. stack: "a",
  764. data: [],
  765. },
  766. {
  767. name: "5~7m风速",
  768. type: "bar",
  769. stack: "a",
  770. data: [],
  771. },
  772. {
  773. name: "7~9m风速",
  774. type: "bar",
  775. stack: "a",
  776. data: [],
  777. },
  778. {
  779. name: "9~11m风速",
  780. type: "bar",
  781. stack: "a",
  782. data: [],
  783. },
  784. {
  785. name: "11~20m风速",
  786. type: "bar",
  787. stack: "a",
  788. data: [],
  789. },
  790. {
  791. name: "20~25m风速",
  792. type: "bar",
  793. stack: "a",
  794. data: [],
  795. },
  796. ];
  797. for (const wtObj of jsonData.timeData) {
  798. barxAxis.data.push(wtObj.wtId);
  799. for (const timeKey in wtObj.time1) {
  800. barSeries.value[timeKey].data.push(
  801. (wtObj.time1[timeKey] / 60).toFixed(0)
  802. );
  803. }
  804. for (const time2Key in wtObj.time2) {
  805. barUnWorkSeries.value[time2Key].data.push(
  806. (wtObj.time2[time2Key] / 60).toFixed(0)
  807. );
  808. }
  809. }
  810. tmDialog.value = true;
  811. });
  812. }
  813. };
  814. /**额定功率 */
  815. const powerDialog = ref(false);
  816. const powerxAxis = reactive({
  817. type: "category",
  818. data: [],
  819. splitLine: {
  820. show: false,
  821. },
  822. axisTick: {
  823. show: true,
  824. },
  825. });
  826. const poweryAxis = ref({
  827. type: "value",
  828. name: "kW",
  829. max: null,
  830. splitLine: {
  831. show: false,
  832. },
  833. axisTick: {
  834. show: true,
  835. },
  836. });
  837. const countyAxis = ref({
  838. type: "value",
  839. name: "次数",
  840. splitLine: {
  841. show: false,
  842. },
  843. axisTick: {
  844. show: true,
  845. },
  846. });
  847. const powerSeries = ref([
  848. {
  849. name: "平均全功率",
  850. type: "bar",
  851. data: [],
  852. markLine: {},
  853. },
  854. ]);
  855. const countSeries = ref([
  856. {
  857. name: "次数",
  858. type: "bar",
  859. data: [],
  860. markLine: {},
  861. },
  862. ]);
  863. const funPower = () => {
  864. if (seriesData.value.length) {
  865. //获取数据
  866. const res = httpRequest
  867. .get("/rated/power", {
  868. params: {
  869. ids: excelCheckIds.value.join(","),
  870. },
  871. })
  872. .then((res) => {
  873. if (res.code === 200) {
  874. powerxAxis.data = [];
  875. powerSeries.value = [
  876. {
  877. name: "平均全功率",
  878. type: "bar",
  879. data: [],
  880. markLine: {
  881. symbol: "none",
  882. label: {
  883. show: true,
  884. },
  885. lineStyle: {
  886. color: "rgba(96,174,255, 1)",
  887. },
  888. data: [],
  889. },
  890. },
  891. ];
  892. countSeries.value = [
  893. {
  894. name: "次数",
  895. type: "bar",
  896. data: [],
  897. markLine: {},
  898. },
  899. ];
  900. if (res.data.data) {
  901. const xAxis = [],
  902. seriesArr = [],
  903. countArr = [];
  904. for (const val of res.data.data) {
  905. xAxis.push(val.wt);
  906. seriesArr.push(val.avg);
  907. countArr.push(val.count);
  908. }
  909. powerxAxis.data = xAxis;
  910. countSeries.value[0].data = countArr.map((o) => {
  911. return {
  912. value: o,
  913. // itemStyle: {
  914. // color: o < res.data.avg ? 'rgb(197,78,82)' : 'rgb(50,93,171)'
  915. // }
  916. };
  917. });
  918. powerSeries.value[0].data = seriesArr.map((o) => {
  919. return {
  920. value: o,
  921. itemStyle: {
  922. color: o < res.data.avg ? "rgb(197,78,82)" : "rgb(50,93,171)",
  923. },
  924. };
  925. });
  926. let maxValue = Math.max(...seriesArr);
  927. if (res.data.power > maxValue) {
  928. maxValue = res.data.power;
  929. } else {
  930. maxValue = null;
  931. }
  932. poweryAxis.value.max = maxValue;
  933. powerSeries.value[0].markLine.data = [
  934. {
  935. yAxis: res.data.avg,
  936. name: `平均额定功率${res.data.avg}`,
  937. lineStyle: {
  938. color: "green",
  939. },
  940. },
  941. {
  942. yAxis: res.data.power,
  943. name: `额定功率${res.data.power}`,
  944. lineStyle: {
  945. color: "red",
  946. },
  947. },
  948. ];
  949. }
  950. powerDialog.value = true;
  951. }
  952. })
  953. .catch(() => {
  954. powerxAxis.data = [];
  955. powerSeries.value = [
  956. {
  957. name: "平均全功率",
  958. type: "bar",
  959. data: [],
  960. markLine: {
  961. symbol: "none",
  962. label: {
  963. show: true,
  964. },
  965. lineStyle: {
  966. color: "rgba(96,174,255, 1)",
  967. },
  968. data: [],
  969. },
  970. },
  971. ];
  972. countSeries.value = [
  973. {
  974. name: "次数",
  975. type: "bar",
  976. data: [],
  977. markLine: {},
  978. },
  979. ];
  980. const xAxis = [],
  981. seriesArr = [],
  982. countArr = [];
  983. for (const val of jsonData.powerData.data) {
  984. xAxis.push(val.wt);
  985. seriesArr.push(val.avg);
  986. countArr.push(val.count);
  987. }
  988. powerxAxis.data = xAxis;
  989. countSeries.value[0].data = countArr.map((o) => {
  990. return {
  991. value: o,
  992. // itemStyle: {
  993. // color: o < res.data.avg ? 'rgb(197,78,82)' : 'rgb(50,93,171)'
  994. // }
  995. };
  996. });
  997. powerSeries.value[0].data = seriesArr.map((o) => {
  998. return {
  999. value: o,
  1000. itemStyle: {
  1001. color: o < res.data.avg ? "rgb(197,78,82)" : "rgb(50,93,171)",
  1002. },
  1003. };
  1004. });
  1005. let maxValue = Math.max(...seriesArr);
  1006. if (jsonData.powerData.power > maxValue) {
  1007. maxValue = res.data.power;
  1008. } else {
  1009. maxValue = null;
  1010. }
  1011. poweryAxis.value.max = maxValue;
  1012. powerSeries.value[0].markLine.data = [
  1013. {
  1014. yAxis: res.data.avg,
  1015. name: `平均额定功率${res.data.avg}`,
  1016. lineStyle: {
  1017. color: "green",
  1018. },
  1019. },
  1020. {
  1021. yAxis: res.data.power,
  1022. name: `额定功率${res.data.power}`,
  1023. lineStyle: {
  1024. color: "red",
  1025. },
  1026. },
  1027. ];
  1028. powerDialog.value = true;
  1029. });
  1030. }
  1031. };
  1032. /**dialog 数据 */
  1033. const wtDialog = ref(false);
  1034. const wtData = ref([]);
  1035. const activeTab = ref("1");
  1036. /**created */
  1037. // funGetTree()
  1038. // funGetProcessTree()
  1039. const theme = ref(null);
  1040. const echartsTheme = ref("");
  1041. const store = useStore();
  1042. watch(
  1043. () => store.state.theme,
  1044. (newVal, oldVal) => {
  1045. theme.value = newVal;
  1046. echartsTheme.value = !newVal ? "dark" : "";
  1047. funGetTree();
  1048. },
  1049. {
  1050. deep: true,
  1051. }
  1052. );
  1053. const initPageData = () => {
  1054. actTreeNode.value = null;
  1055. treeData.value = funRepeatMap(JSON.parse(JSON.stringify(jsonData.treeData)));
  1056. excelList.value = [];
  1057. nextTick(() => {
  1058. if (actTreeNode.value) {
  1059. if (actTreeNode.value.childs) {
  1060. excelList.value = actTreeNode.value.childs.map((o) => {
  1061. return {
  1062. id: o.id,
  1063. interval: o.interval,
  1064. path: o.path,
  1065. prepareid: o.prepareid,
  1066. station: o.station,
  1067. time: o.time,
  1068. type: o.type,
  1069. windturbine: o.windturbine,
  1070. isCheck: false,
  1071. name: o.path.substring(
  1072. o.path.indexOf(o.station + "_") + (o.station + "_").length
  1073. ),
  1074. };
  1075. });
  1076. } else {
  1077. excelList.value = [];
  1078. }
  1079. if (treeCopRef.value && treeCopRef.value.data) {
  1080. treeCopRef.value.$refs.tree.setCheckedKeys(
  1081. [actTreeNode.value.id],
  1082. true
  1083. );
  1084. excelCheckIds.value = [actTreeNode.value.childs[0].id];
  1085. wtData.value = [];
  1086. seriesData.value = [];
  1087. seriesData.value.push({
  1088. name: "保证功率",
  1089. type: "line",
  1090. symbol: "line", //设定为实心点
  1091. symbolSize: 0, //设定实心点的大小
  1092. smooth: true, //这个是把线变成曲线
  1093. data: jsonData.lineData.bzgl || [],
  1094. xAxisIndex: 0,
  1095. });
  1096. for (const wtObj of jsonData.lineData.sjgl) {
  1097. seriesData.value.push({
  1098. // name: wtObj.obj.windturbineId + "\n实际功率",
  1099. name: wtObj.obj.code + "\n实际功率",
  1100. type: "line",
  1101. symbol: "line", //设定为实心点
  1102. symbolSize: 0, //设定实心点的大小
  1103. smooth: true, //这个是把线变成曲线
  1104. data: wtObj.sjgl || [],
  1105. xAxisIndex: 0,
  1106. });
  1107. wtData.value.push(wtObj.obj);
  1108. }
  1109. }
  1110. }
  1111. });
  1112. };
  1113. /**mounted */
  1114. onMounted(() => {
  1115. initPageData();
  1116. funGetTree();
  1117. theme.value = store.state.theme;
  1118. echartsTheme.value = !theme.value ? "dark" : "";
  1119. tableHeight.value = window.innerHeight - 140 + "px";
  1120. excelHeight.value = window.innerHeight - 140 + "px";
  1121. treeHeight.value = window.innerHeight - 140 + "px";
  1122. window.addEventListener("resize", () => {
  1123. tableHeight.value = window.innerHeight - 140 + "px";
  1124. excelHeight.value = window.innerHeight - 140 + "px";
  1125. treeHeight.value = window.innerHeight - 140 + "px";
  1126. });
  1127. /**test */
  1128. // funExcelChange({
  1129. // id: 1,
  1130. // name: 'excel',
  1131. // type: 'fitting',
  1132. // })
  1133. });
  1134. /**activated */
  1135. // onActivated(() => {
  1136. // funGetTree()
  1137. // })
  1138. </script>
  1139. <style lang="less" scoped>
  1140. .dataAnalysisLineAna {
  1141. height: 100%;
  1142. .dataAnalysisLineAnaMain {
  1143. height: 100%;
  1144. .main_top {
  1145. height: 40px;
  1146. display: flex;
  1147. align-items: center;
  1148. .topPsty {
  1149. position: relative;
  1150. top: 5px;
  1151. padding: 7px 20px;
  1152. font-size: 12px;
  1153. font-weight: 600;
  1154. margin-left: 10px;
  1155. border-radius: 3px;
  1156. }
  1157. }
  1158. .main {
  1159. display: flex;
  1160. width: 100%;
  1161. .treeDataMain,
  1162. .excelDataMain,
  1163. .tableDataMain {
  1164. border-radius: 10px;
  1165. }
  1166. .treeDataMain {
  1167. margin-right: 10px;
  1168. padding: 10px 0 10px 10px;
  1169. width: calc(19% - 20px);
  1170. }
  1171. .excelDataMain {
  1172. margin-right: 10px;
  1173. padding: 10px 0 10px 10px;
  1174. width: calc(15% - 20px);
  1175. }
  1176. .tableDataMain {
  1177. padding: 10px;
  1178. width: calc(66% - 20px);
  1179. position: relative;
  1180. .butten_com {
  1181. position: absolute;
  1182. right: 20px;
  1183. z-index: 111111;
  1184. }
  1185. }
  1186. }
  1187. }
  1188. }
  1189. .themeDark {
  1190. .dataAnalysisLineAnaMain {
  1191. .main_top {
  1192. .topPsty {
  1193. color: #1c99ff;
  1194. background: #1e2126;
  1195. }
  1196. }
  1197. .main {
  1198. background: #13171e;
  1199. .treeDataMain {
  1200. background: transparent;
  1201. }
  1202. .excelDataMain {
  1203. background: #313233;
  1204. }
  1205. .tableDataMain {
  1206. margin-top: 5px;
  1207. background: #212223;
  1208. }
  1209. }
  1210. }
  1211. }
  1212. .themeLight {
  1213. padding: 0;
  1214. .dataAnalysisLineAnaMain {
  1215. .main_top {
  1216. .topPsty {
  1217. color: #2778ff;
  1218. background: #ffffff;
  1219. }
  1220. }
  1221. .main {
  1222. background: #e6e8f2;
  1223. .treeDataMain {
  1224. background: transparent;
  1225. }
  1226. .excelDataMain {
  1227. background: #f4f6fb;
  1228. }
  1229. .tableDataMain {
  1230. background: #fff;
  1231. margin-top: 5px;
  1232. }
  1233. }
  1234. }
  1235. }
  1236. </style>