dayBatterDialog.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. <template>
  2. <el-dialog custom-class="windLifeDialog" :title="title" v-model="dialogVisible" :fullscreen="true"
  3. :close-on-click-modal="false" @close="closeDialog">
  4. <div class="globalDiaMain" :class="!theme ? 'themeDa' : 'themeLi'">
  5. <div class="main_top">
  6. <div class="main_top_left">
  7. <div class="exceed">
  8. <span style="margin-top: 3px">时间:</span>
  9. <el-date-picker v-model="dateVal" type="datetimerange" :clearable="false" range-separator="至"
  10. start-placeholder="开始日期" end-placeholder="结束日期">
  11. </el-date-picker>
  12. </div>
  13. <div class="exceed">
  14. <span style="margin-top: 3px">超前:</span>
  15. <el-select style="width: 130px" class="exTime" v-model="chooseExceedTimeFv" placeholder="请选择">
  16. <el-option v-for="item in ExceedTimeList" :key="item.value" :label="item.label"
  17. :disabled="item.disabled" :value="item.value">
  18. </el-option>
  19. </el-select>
  20. </div>
  21. <!-- <div class="exceed">
  22. <span style="margin-top: 3px;">间隔:</span>
  23. <el-select class="exTime" v-model="rJianStr" placeholder="请选择">
  24. <el-option v-for="item in rJian" :key="item.value" :label="item.label"
  25. :disabled="item.disabled" :value="item.value">
  26. </el-option>
  27. </el-select>
  28. </div> -->
  29. <el-button type="primary" @click="seachData">查 询</el-button>
  30. <el-button @click="exportExcel">导出查询结果</el-button>
  31. </div>
  32. </div>
  33. <div v-loading="loading">
  34. <div class="main_charts">
  35. <div id="centerCharts" class="chartsStyle"></div>
  36. </div>
  37. <div class="main_table warn-table" style="margin-top: 20px">
  38. <el-table :data="tableData" ref="report-table_day" border max-height="45vh" style="width: 100%"
  39. :header-cell-style="{
  40. padding: '4px',
  41. fontSize: '16px',
  42. fontWeight: bold,
  43. border: '0.5px solid rgba(0,0,0,.5) !important',
  44. }">
  45. <el-table-column prop="dataTime" label="时间" align="center" width="160"></el-table-column>
  46. <el-table-column prop="theoreticalPower" label="理论电量" align="center"></el-table-column>
  47. <el-table-column prop="availablePower" label="可用电量" align="center"></el-table-column>
  48. <el-table-column label="当期数据" align="center">
  49. <el-table-column prop="actualPowerDq" label="实际电量" align="center"></el-table-column>
  50. <el-table-column prop="veryShortTermForecastDq" label="超短期预测" align="center">
  51. <el-table-column prop="veryShortTermForecastDq" label="累计" align="center">
  52. </el-table-column>
  53. <el-table-column prop="veryTimeVs" label="时刻" align="center"></el-table-column>
  54. </el-table-column>
  55. <el-table-column prop="shortTermForecastDq" label="短期预测" align="center">
  56. <el-table-column prop="shortTermForecastDq" label="累计" align="center"></el-table-column>
  57. <el-table-column prop="shortTimeVs" label="时刻" align="center"></el-table-column>
  58. </el-table-column>
  59. </el-table-column>
  60. <el-table-column label="同期数据" align="center">
  61. <el-table-column prop="actualPowerTq" label="实际电量" align="center"></el-table-column>
  62. <el-table-column prop="veryShortTermForecastTq" label="超短期预测" align="center">
  63. </el-table-column>
  64. <el-table-column prop="shortTermForecastTq" label="短期预测" align="center"></el-table-column>
  65. </el-table-column>
  66. <el-table-column label="同期比率" align="center">
  67. <el-table-column prop="tqActualRatio" label="实际电量" align="center"></el-table-column>
  68. <el-table-column prop="tqUltraRatio" label="超短期预测" align="center"></el-table-column>
  69. <el-table-column prop="tqShortRatio" label="短期预测" align="center"></el-table-column>
  70. </el-table-column>
  71. </el-table>
  72. </div>
  73. </div>
  74. </div>
  75. </el-dialog>
  76. </template>
  77. <script>
  78. import * as XLSX from "xlsx";
  79. import {
  80. saveAs
  81. } from "file-saver";
  82. import * as XLSXD from "xlsx-js-style";
  83. import {
  84. apiGetdailyPowerComparisonChartData,
  85. apiGetdailyPowerComparisonTableData,
  86. } from "../../../api/api";
  87. export default {
  88. props: {
  89. from: {
  90. type: String,
  91. default: () => {
  92. return "";
  93. },
  94. },
  95. ExceedTimeList: {
  96. type: Array,
  97. default: () => {
  98. return [];
  99. },
  100. },
  101. stationData: {
  102. type: Array,
  103. default: () => {
  104. return [];
  105. },
  106. },
  107. echartsTheme: {
  108. type: String,
  109. default: () => {
  110. return "";
  111. },
  112. },
  113. theme: {
  114. type: Boolean,
  115. default: () => {
  116. return false;
  117. },
  118. },
  119. },
  120. data() {
  121. return {
  122. title: "",
  123. dialogVisible: false,
  124. windTurbines: null,
  125. windTurbinesVal: null,
  126. tableData: [],
  127. chooseExceedTimeFv: 0,
  128. rJianStr: 1,
  129. dateVal: [],
  130. loading: false,
  131. rJian: [],
  132. fakeFs: [{
  133. name: "预测风速",
  134. data: [
  135. 1.5, 5.7, 7, 3, 4, 9, 5, 4, 2, 3, 9, 0, 4, 5, 8, 6.4, 4, 9, 3, 2, 7,
  136. 1, 5, 2,
  137. ],
  138. },
  139. {
  140. name: "实际风速",
  141. data: [
  142. 7.1, 5.9, 6, 4, 1, 2, 9, 5, 4, 5, 7, 1, 6, 9, 5, 3, 4, 2, 4, 5.6, 9,
  143. 1, 4.4, 3,
  144. ],
  145. },
  146. ],
  147. };
  148. },
  149. created() {
  150. this.rJian = [{
  151. label: "15分钟",
  152. value: 1,
  153. },
  154. {
  155. label: "1小时",
  156. value: 2,
  157. },
  158. ];
  159. },
  160. methods: {
  161. closeDialog() {
  162. this.dialogVisible = false;
  163. },
  164. seachData() {
  165. this.loading = true;
  166. this.getChartsData();
  167. this.getTableData();
  168. },
  169. allStationData() {
  170. this.getChartsData();
  171. this.getTableData();
  172. },
  173. chooseVal(val) {
  174. this.stationData.forEach((item) => {
  175. if (item.no === val) {
  176. this.windTurbinesVal = item.itemVal;
  177. }
  178. });
  179. },
  180. // 日发电量预测echarts
  181. getChartsData() {
  182. let that = this;
  183. let pickStartTime = that.getElecTime(that.dateVal[0]);
  184. let pickStartTime15 = that.getElecTime(that.dateVal[0], "15");
  185. let pickEndTime = that.getElecTime(that.dateVal[1]);
  186. let pickEndTime15 = that.getElecTime(that.dateVal[1], "15");
  187. let params = {
  188. beginDataTime: pickStartTime,
  189. beginDataTime15: pickStartTime15,
  190. endDataTime: pickEndTime,
  191. endDataTime15: pickEndTime15,
  192. leadTime: that.chooseExceedTimeFv,
  193. stationNumber: that.windTurbines,
  194. itemVal: that.windTurbinesVal,
  195. // jg: that.rJianStr
  196. jg: 1,
  197. };
  198. apiGetdailyPowerComparisonChartData(params).then((datas) => {
  199. if (datas && datas.data) {
  200. let xAxis = [];
  201. let series = [];
  202. let legend = [];
  203. if (datas.data.dateList.length > 0) {
  204. // datas.data.dateList.forEach(item =>{
  205. // xAxis.push(item.substring(item.indexOf(' '), item.length))
  206. // })
  207. xAxis = datas.data.dateList;
  208. }
  209. if (datas.data.dataFormatList.length > 0) {
  210. datas.data.dataFormatList.forEach((iten) => {
  211. legend.push(iten.name);
  212. let seriesObj = {
  213. name: iten.name,
  214. type: "line",
  215. data: iten.data.map((it) => {
  216. return that.$utils.isHasNum(it);
  217. }),
  218. symbol: "none",
  219. };
  220. series.push(seriesObj);
  221. });
  222. }
  223. that.getglobalLine("centerCharts", xAxis, legend, series);
  224. }
  225. });
  226. },
  227. getglobalLine(name, xAxis, legend, series) {
  228. const seriesFindFs = series.some((ele) => {
  229. return ele.name.indexOf("风速") !== -1;
  230. });
  231. if (!seriesFindFs) {
  232. this.fakeFs.forEach((ele) => {
  233. series.push(ele);
  234. });
  235. }
  236. const legendFindFs = legend.some((ele) => {
  237. return ele.indexOf("风速") !== -1;
  238. });
  239. if (!seriesFindFs) {
  240. this.fakeFs.forEach((ele) => {
  241. legend.push(ele.name);
  242. });
  243. }
  244. let powerLineData = [];
  245. let fsLineData = [];
  246. series.forEach((ele) => {
  247. ele.type = ele.type || "line";
  248. if (ele.name.indexOf("风速") !== -1) {
  249. ele.yAxisIndex = 1;
  250. fsLineData.push(ele.data);
  251. } else {
  252. ele.yAxisIndex = 0;
  253. powerLineData.push(ele.data);
  254. }
  255. });
  256. powerLineData.forEach((pEle) => {
  257. for (let i = 0; i < pEle.length; i++) {
  258. if (pEle[i] === "-") {
  259. pEle.splice(i, 1);
  260. i--;
  261. }
  262. }
  263. });
  264. fsLineData.forEach((pEle) => {
  265. for (let i = 0; i < pEle.length; i++) {
  266. if (pEle[i] === "-") {
  267. pEle.splice(i, 1);
  268. i--;
  269. }
  270. }
  271. });
  272. const allPowerData = [].concat(...powerLineData);
  273. const powerMin = Math.min(...allPowerData);
  274. const powerMax = Math.max(...allPowerData);
  275. const allWindData = [].concat(...fsLineData);
  276. const windSpeedMin = Math.min(...allWindData);
  277. const windSpeedMax = Math.max(...allWindData);
  278. const splitNumber = 5;
  279. let option = {
  280. title: {
  281. text: "电量",
  282. },
  283. tooltip: {
  284. trigger: "axis",
  285. },
  286. legend: {
  287. right: "20",
  288. data: legend,
  289. },
  290. grid: {
  291. left: "5%",
  292. right: "4%",
  293. bottom: "3%",
  294. containLabel: true,
  295. },
  296. xAxis: {
  297. type: "category",
  298. boundaryGap: false,
  299. data: xAxis,
  300. },
  301. yAxis: [{
  302. type: "value",
  303. name: "万千瓦时(Wkw/h)",
  304. splitLine: {
  305. lineStyle: {
  306. color: this.$store.state.theme ? "#000" : "#ccc",
  307. type: "dashed", // 修改为虚线
  308. opacity: 0.2,
  309. },
  310. },
  311. min: powerMin,
  312. max: powerMax, // 动态设置最大值
  313. interval: parseFloat(
  314. ((powerMax - powerMin) / splitNumber).toFixed(4)
  315. ),
  316. splitNumber,
  317. axisLabel: {
  318. formatter(value) {
  319. return parseInt(value);
  320. },
  321. },
  322. },
  323. {
  324. type: "value",
  325. name: "风速(m/s)",
  326. splitLine: {
  327. lineStyle: {
  328. color: this.$store.state.theme ? "#000" : "#ccc",
  329. type: "dashed", // 修改为虚线
  330. opacity: 0.2,
  331. },
  332. },
  333. min: windSpeedMin,
  334. max: windSpeedMax, // 动态设置最大值
  335. splitNumber,
  336. interval: parseFloat(
  337. ((windSpeedMax - windSpeedMin) / splitNumber).toFixed(4)
  338. ),
  339. axisLabel: {
  340. formatter(value) {
  341. return parseFloat(value.toFixed(1));
  342. },
  343. },
  344. },
  345. ],
  346. series: series,
  347. };
  348. if (this.from === "index") {
  349. option.backgroundColor = "";
  350. }
  351. if (!this.theme) {
  352. option.backgroundColor = "";
  353. }
  354. // 基于准备好的dom,初始化echarts实例
  355. let dom = document.getElementById(name);
  356. dom.removeAttribute("_echarts_instance_") ?
  357. dom.removeAttribute("_echarts_instance_") :
  358. "";
  359. let myChart = this.$echarts.init(dom, this.echartsTheme);
  360. myChart.setOption(option);
  361. window.addEventListener("resize", function () {
  362. myChart.resize();
  363. });
  364. },
  365. // 日发电量预测table
  366. getTableData() {
  367. let that = this;
  368. let pickStartTime = that.getElecTime(that.dateVal[0]);
  369. let pickStartTime15 = that.getElecTime(that.dateVal[0], "15");
  370. let pickEndTime = that.getElecTime(that.dateVal[1]);
  371. let pickEndTime15 = that.getElecTime(that.dateVal[1], "15");
  372. that.tableData = [];
  373. let params = {
  374. beginDataTime: pickStartTime,
  375. beginDataTime15: pickStartTime15,
  376. endDataTime: pickEndTime,
  377. endDataTime15: pickEndTime15,
  378. leadTime: that.chooseExceedTimeFv,
  379. stationNumber: that.windTurbines,
  380. itemVal: that.windTurbinesVal,
  381. // jg: that.rJianStr
  382. jg: 1,
  383. };
  384. apiGetdailyPowerComparisonTableData(params).then((datas) => {
  385. if (datas && datas.data) {
  386. that.loading = false;
  387. if (datas.data.dataFormatList) {
  388. datas.data.dataFormatList.forEach((item) => {
  389. for (let i in item) {
  390. if (i !== "dataTime") {
  391. item[i] = that.$utils.isHasNum(item[i]);
  392. }
  393. }
  394. //同期实际比率
  395. item.tqActualRatio = that.$utils.ratioCalculation(
  396. item.actualPowerDq,
  397. item.actualPowerTq
  398. );
  399. //同期超短期比率
  400. item.tqUltraRatio = that.$utils.ratioCalculation(
  401. item.veryShortTermForecastDq,
  402. item.veryShortTermForecastTq
  403. );
  404. //同期短期比率
  405. item.tqShortRatio = that.$utils.ratioCalculation(
  406. item.shortTermForecastDq,
  407. item.shortTermForecastTq
  408. );
  409. });
  410. that.tableData = datas.data.dataFormatList;
  411. for (let i = 0; i < that.tableData.length; i++) {
  412. let item = that.tableData[i];
  413. let items = that.tableData[i + 1];
  414. if (i === 0) {
  415. item.veryTimeVs = item.veryShortTermForecastDq;
  416. item.shortTimeVs = item.shortTermForecastDq;
  417. if (
  418. item.veryShortTermForecastDq !== "-" &&
  419. items.veryShortTermForecastDq !== "-"
  420. ) {
  421. items.veryTimeVs = Number(
  422. Number(items.veryShortTermForecastDq) -
  423. Number(item.veryShortTermForecastDq)
  424. ).toFixed(2);
  425. } else {
  426. items.veryTimeVs = "-";
  427. }
  428. if (
  429. item.shortTermForecastDq !== "-" &&
  430. items.shortTermForecastDq !== "-"
  431. ) {
  432. items.shortTimeVs = Number(
  433. Number(items.shortTermForecastDq) -
  434. Number(item.shortTermForecastDq)
  435. ).toFixed(2);
  436. } else {
  437. items.shortTimeVs = "-";
  438. }
  439. } else {
  440. if (items) {
  441. if (
  442. item.veryShortTermForecastDq !== "-" &&
  443. items.veryShortTermForecastDq !== "-"
  444. ) {
  445. items.veryTimeVs = Number(
  446. Number(items.veryShortTermForecastDq) -
  447. Number(item.veryShortTermForecastDq)
  448. ).toFixed(2);
  449. } else {
  450. items.veryTimeVs = "-";
  451. }
  452. if (
  453. item.shortTermForecastDq !== "-" &&
  454. items.shortTermForecastDq !== "-"
  455. ) {
  456. items.shortTimeVs = Number(
  457. Number(items.shortTermForecastDq) -
  458. Number(item.shortTermForecastDq)
  459. ).toFixed(2);
  460. } else {
  461. items.shortTimeVs = "-";
  462. }
  463. }
  464. // else {
  465. // items.veryTimeVs = '-'
  466. // items.shortTimeVs = '-'
  467. // }
  468. }
  469. }
  470. }
  471. }
  472. });
  473. },
  474. //转换时间
  475. getElecTime(date, type) {
  476. var y = date.getFullYear();
  477. var m = date.getMonth() + 1;
  478. m = m < 10 ? "0" + m : m;
  479. var d = date.getDate();
  480. d = d < 10 ? "0" + d : d;
  481. var h = date.getHours();
  482. h = h < 10 ? "0" + h : h;
  483. var minute = date.getMinutes();
  484. minute = minute < 10 ? "0" + minute : minute;
  485. let timeF = "";
  486. timeF = y + "-" + m + "-" + d + " " + h + ":" + minute;
  487. if (type !== "15") {
  488. return this.$utils.changeElectricPickDate(timeF) + ":00";
  489. } else {
  490. return this.$utils.changePowerPickDate(timeF) + ":00";
  491. }
  492. },
  493. exportExcel() {
  494. let $e = this.$refs["report-table_day"].$el;
  495. try {
  496. let $table = $e.querySelector(".el-table__fixed");
  497. if (!$table) {
  498. $table = $e;
  499. }
  500. const wb = XLSX.utils.table_to_book($table, {
  501. raw: true,
  502. });
  503. if (wb && wb.Sheets.Sheet1) {
  504. let as = ["!cols", "!fullref", "!merges", "!ref", "!rows"];
  505. let bs = [
  506. "时间",
  507. "理论电量",
  508. "当期数据",
  509. "可用电量",
  510. "实际电量",
  511. "超短期预测",
  512. "短期预测",
  513. "同期数据",
  514. "同期比率",
  515. "环比数据",
  516. "环比比率",
  517. "累计",
  518. "时刻",
  519. ];
  520. for (let i in wb.Sheets.Sheet1) {
  521. if (as.indexOf(i) < 0) {
  522. if (bs.indexOf(wb.Sheets.Sheet1[i].v) >= 0) {
  523. wb.Sheets.Sheet1[i].s = {
  524. font: {
  525. name: "微软雅黑",
  526. sz: 11,
  527. bold: true,
  528. color: {
  529. rgb: "ffffff",
  530. },
  531. },
  532. alignment: {
  533. horizontal: "center",
  534. vertical: "center",
  535. },
  536. fill: {
  537. fgColor: {
  538. rgb: "4f81bd",
  539. },
  540. },
  541. };
  542. if (i === "A1") {
  543. wb.Sheets.Sheet1["!cols"].push({
  544. wch: 30,
  545. });
  546. } else if (i === "B1") {
  547. wb.Sheets.Sheet1["!cols"].push({
  548. wch: 20,
  549. });
  550. } else {
  551. wb.Sheets.Sheet1["!cols"].push({
  552. wch: 15,
  553. });
  554. }
  555. } else {
  556. wb.Sheets.Sheet1[i].s = {
  557. font: {
  558. name: "微软雅黑",
  559. sz: 10,
  560. bold: false,
  561. color: {
  562. rgb: "000000",
  563. },
  564. },
  565. alignment: {
  566. horizontal: "center",
  567. vertical: "center",
  568. },
  569. // fill:{fgColor: {rgb: '4f81bd'}}
  570. };
  571. }
  572. }
  573. }
  574. }
  575. const wbout = XLSXD.write(wb, {
  576. bookType: "xlsx",
  577. bookSST: true,
  578. type: "array",
  579. });
  580. saveAs(
  581. new Blob([wbout], {
  582. type: "application/octet-stream",
  583. }),
  584. `${this.title}.xlsx`
  585. );
  586. } catch (e) {
  587. if (typeof console !== "undefined") console.error(e);
  588. }
  589. },
  590. },
  591. };
  592. </script>
  593. <style lang="less">
  594. .globalDiaMain {
  595. .main_top {
  596. .main_top_left {
  597. .exceed {
  598. .el-date-editor {
  599. .el-input__prefix {
  600. margin-left: 5px !important;
  601. }
  602. }
  603. }
  604. }
  605. }
  606. }
  607. .themeDa {
  608. .main_top {
  609. .main_top_left {
  610. .exceed {
  611. color: #fff;
  612. }
  613. }
  614. }
  615. }
  616. .themeLi {
  617. .main_top {
  618. .main_top_left {
  619. .exceed {
  620. color: #000;
  621. }
  622. }
  623. }
  624. }
  625. </style>