index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. <template>
  2. <div class="powerLinefitting">
  3. <div class="powerLinefitting_topAll">
  4. <div class="powerLinefitting_top">
  5. <el-select
  6. size="mini"
  7. v-model="companyVal"
  8. placeholder="请选择"
  9. @change="changeCompan"
  10. >
  11. <el-option
  12. v-for="item in companyOptions"
  13. :key="item.id"
  14. :label="item.aname"
  15. :value="item.id"
  16. >
  17. </el-option>
  18. </el-select>
  19. <div class="tabCut">
  20. <div
  21. @click="changeBtn(val.id)"
  22. :class="tabEvent === val.id ? 'active' : ''"
  23. v-for="val in tabOptions"
  24. :key="val.id"
  25. >
  26. <span>{{ val.name }}</span>
  27. </div>
  28. </div>
  29. <div class="station">
  30. 场站:
  31. <el-select
  32. size="mini"
  33. v-model="stationVal"
  34. placeholder="请选择"
  35. clearable
  36. @change="changeStation"
  37. >
  38. <el-option
  39. v-for="item in stationOptions"
  40. :key="item.id"
  41. :label="item.name"
  42. :value="item.id"
  43. >
  44. </el-option>
  45. </el-select>
  46. </div>
  47. <div class="station">
  48. 风机:
  49. <el-select
  50. size="mini"
  51. v-model="windVal"
  52. placeholder="请选择"
  53. clearable
  54. >
  55. <el-option
  56. v-for="item in windsOptions"
  57. :key="item.id"
  58. :label="item.name"
  59. :value="item.id"
  60. >
  61. </el-option>
  62. </el-select>
  63. </div>
  64. <div class="but">
  65. <el-button round size="mini" class="buttons" @click="seachData"
  66. >拟合</el-button
  67. >
  68. <el-button round size="mini" class="buttons" @click="downXlsxFn"
  69. >导出</el-button
  70. >
  71. </div>
  72. </div>
  73. <div class="selections">
  74. <div
  75. class="selections_btn"
  76. @click="tabSelect(0)"
  77. :class="{ active: tabIndex == 0 }"
  78. >
  79. </div>
  80. <div
  81. class="selections_btn"
  82. @click="tabSelect(1)"
  83. :class="{ active: tabIndex == 1 }"
  84. >
  85. </div>
  86. <div
  87. class="selections_btn"
  88. @click="tabSelect(2)"
  89. :class="{ active: tabIndex == 2 }"
  90. >
  91. </div>
  92. </div>
  93. </div>
  94. <div style="background: rgba(0, 0, 0, 0.4)">
  95. <div class="powerLinefitting_title clearfix">
  96. <div class="leftContent floatLeft"><span>功率曲线拟合</span></div>
  97. <div class="rightContent floatRight"></div>
  98. </div>
  99. <div class="powerLinefitting_Table">
  100. <el-table
  101. :data="powerLinefittingData"
  102. stripe
  103. size="mini"
  104. height="48vh"
  105. ref="fitting_table"
  106. style="width: 100%"
  107. >
  108. <el-table-column
  109. v-for="(item, index) in tableHeader"
  110. :key="index"
  111. sortable
  112. :prop="item.code"
  113. :label="item.title"
  114. align="center"
  115. >
  116. </el-table-column>
  117. </el-table>
  118. </div>
  119. </div>
  120. <div class="powerLinefitting_Echarts">
  121. <div class="chart-name">
  122. <div class="point point-left bottom"></div>
  123. <div class="point point-right bottom"></div>
  124. <span>功率曲线</span>
  125. </div>
  126. <div id="fittingid" class="fittingEchartSty"></div>
  127. </div>
  128. </div>
  129. </template>
  130. <script>
  131. import {
  132. getApicompanyslist,
  133. getApiwpByCplistlist,
  134. getApiequipmentList,
  135. getApiPerformancecurvefitting,
  136. } from "@/api/monthlyPerformanceAnalysis";
  137. import * as echarts from "echarts";
  138. import partten from "@/helper/partten.js";
  139. import util from "@/helper/util.js";
  140. import utils from "@/utills/downXlsx";
  141. export default {
  142. name: "powerLinefitting",
  143. data() {
  144. return {
  145. tabIndex: 0,
  146. companyVal: "",
  147. companyOptions: [],
  148. stationVal: "",
  149. stationOptions: [],
  150. windVal: "",
  151. windsOptions: [],
  152. powerLinefittingData: [],
  153. powerLinefitData: [],
  154. tableHeader: [
  155. { title: "名称", code: "nemCode" },
  156. { title: "风速(m/s)", code: "speed" },
  157. { title: "保证功率(KW)", code: "ensurepower" },
  158. { title: "拟合功率(KW)", code: "theorypower" },
  159. ],
  160. tabEvent: -1,
  161. tabOptions: [
  162. { id: -1, name: "风电" },
  163. { id: -2, name: "光伏" },
  164. ],
  165. };
  166. },
  167. created() {
  168. this.getCompanyData();
  169. },
  170. watch: {
  171. tabEvent(val) {
  172. this.tableHeader = this.tableHeader.map((item) => {
  173. if (item.code == "speed") {
  174. if (val == -2) {
  175. item.title = "光照(W/m²)";
  176. } else {
  177. item.title = "风速(m/s)";
  178. }
  179. }
  180. return { ...item };
  181. });
  182. },
  183. },
  184. methods: {
  185. // 切换tab
  186. tabSelect(index) {
  187. this.tabIndex = index;
  188. this.getTableData();
  189. },
  190. changeBtn(id) {
  191. this.tabEvent = id;
  192. this.stationVal = "";
  193. this.stationOptions = [];
  194. this.windVal = "";
  195. this.windsOptions = [];
  196. this.getStationData();
  197. // this.getTableData();
  198. },
  199. // 获取公司列表
  200. async getCompanyData() {
  201. this.companyOptions = [];
  202. this.pickerTimer = this.getchangeTime(new Date());
  203. const { data: datas } = await getApicompanyslist();
  204. this.companyOptions = datas.data;
  205. this.companyVal = datas.data[0]?.id;
  206. this.getStationData(this.companyVal);
  207. },
  208. changeCompan(val) {
  209. this.companyVal = val;
  210. this.stationOptions = [];
  211. this.windsOptions = [];
  212. this.stationVal = "";
  213. this.windVal = "";
  214. this.getStationData();
  215. },
  216. // 获取场站列表
  217. async getStationData() {
  218. this.stationOptions = [];
  219. let params = {
  220. type: this.tabEvent,
  221. companyid: this.companyVal,
  222. };
  223. const { data: datas } = await getApiwpByCplistlist(params);
  224. this.stationOptions = datas.data;
  225. this.stationVal = datas.data[0].id;
  226. this.getWindData();
  227. },
  228. changeStation(val) {
  229. this.stationVal = val;
  230. this.getWindData();
  231. },
  232. // 获取风机
  233. async getWindData() {
  234. this.windsOptions = [];
  235. let params = {
  236. companyId: this.companyVal,
  237. wpIds: this.stationVal,
  238. projectIds: "",
  239. lineIds: "",
  240. type: 0,
  241. };
  242. const { data: datas } = await getApiequipmentList(params);
  243. if (datas.data.length) {
  244. this.windsOptions = datas.data;
  245. this.windVal = datas.data[0].id;
  246. } else {
  247. this.windsOptions = datas.data;
  248. this.windVal = "";
  249. }
  250. this.seachData();
  251. },
  252. seachData() {
  253. this.getTableData();
  254. },
  255. async getTableData() {
  256. let params = {
  257. dateType: this.tabIndex * 1 + 1,
  258. wtId: this.windVal,
  259. type: this.tabEvent,
  260. };
  261. const { data: datas } = await getApiPerformancecurvefitting(params);
  262. console.log("time111===>", new Date().getTime());
  263. this.changeEchartsData(datas.data.chanrt);
  264. datas.data.list.forEach((item) => {
  265. item.speed = item.speed.toFixed(2);
  266. });
  267. this.powerLinefittingData = datas.data.list;
  268. },
  269. // 整合echarts数据
  270. changeEchartsData(datas) {
  271. let xAxis = [];
  272. let lenged = [];
  273. let seriesOne = [];
  274. let seriesTwo = [];
  275. let series = [];
  276. let showYx = false;
  277. if (datas && datas.length > 0) {
  278. showYx = true;
  279. lenged = ["保证功率", "拟合功率"];
  280. datas.forEach((it, index) => {
  281. xAxis.push(it.speed);
  282. seriesOne.push(it.ensurepower);
  283. seriesTwo.push(it.theorypower);
  284. });
  285. let obj = {
  286. name: "保证功率",
  287. type: "line",
  288. smooth: true,
  289. lineStyle: {
  290. width: 1,
  291. },
  292. data: seriesOne,
  293. };
  294. // series.push(obj)
  295. let objs = {
  296. name: "拟合功率",
  297. type: "line",
  298. smooth: true,
  299. lineStyle: {
  300. width: 1,
  301. },
  302. data: seriesTwo,
  303. };
  304. // series.push(objs)
  305. series = [obj, objs];
  306. }
  307. this.getChartes(xAxis, lenged, series, showYx);
  308. },
  309. getChartes(xAxis, lenged, series, showY) {
  310. let option = {
  311. color: [
  312. "#1C99FF",
  313. "#FF8700",
  314. "#3D54BE",
  315. "#fa8c16",
  316. "#1DA0D7",
  317. "#DD5044",
  318. ],
  319. tooltip: {
  320. trigger: "axis",
  321. backgroundColor: "rgba(0,0,0,0.4)",
  322. borderColor: partten.getColor("gray"),
  323. textStyle: {
  324. color: "#fff",
  325. fontSize: util.vh(16),
  326. },
  327. },
  328. legend: {
  329. show: true,
  330. data: lenged,
  331. padding: [10, 10],
  332. right: 56,
  333. icon: "circle",
  334. itemWidth: 6,
  335. inactiveColor: partten.getColor("gray"),
  336. textStyle: {
  337. color: partten.getColor("grayl"),
  338. fontSize: 12,
  339. },
  340. },
  341. grid: {
  342. top: 56,
  343. left: 40,
  344. right: 15,
  345. bottom: 24,
  346. containLabel: true,
  347. },
  348. xAxis: [
  349. {
  350. type: "category",
  351. boundaryGap: false,
  352. axisLabel: {
  353. formatter: "{value}",
  354. textStyle: {
  355. color: partten.getColor("gray"),
  356. fontSize: util.vh(10),
  357. },
  358. },
  359. data: xAxis,
  360. },
  361. ],
  362. yAxis: {
  363. // show: showY,
  364. type: "value",
  365. name: "kWh",
  366. axisLabel: {
  367. formatter: "{value}",
  368. fontSize: "14px",
  369. },
  370. boundaryGap: false,
  371. //分格线
  372. splitLine: {
  373. show: false,
  374. },
  375. },
  376. series: series,
  377. };
  378. let dom = document.getElementById("fittingid");
  379. dom.removeAttribute("_echarts_instance_");
  380. let myChart = echarts.init(dom);
  381. myChart.clear();
  382. myChart.setOption(option);
  383. console.log(222222, new Date().getTime());
  384. window.addEventListener("resize", function () {
  385. myChart.resize();
  386. });
  387. console.log("time222===>", new Date().getTime());
  388. },
  389. //转换时间
  390. getchangeTime(date) {
  391. var y = date.getFullYear();
  392. var m = date.getMonth() + 1;
  393. m = m < 10 ? "0" + m : m;
  394. var d = date.getDate();
  395. d = d < 10 ? "0" + d : d;
  396. return y + "-" + m + "-" + d;
  397. },
  398. downXlsxFn() {
  399. let header = [];
  400. this.tableHeader.forEach((it) => {
  401. header.push(it.title);
  402. });
  403. utils.exportExcel(
  404. this.$refs["fitting_table"].$el,
  405. header,
  406. "功率曲线拟合"
  407. );
  408. },
  409. },
  410. };
  411. </script>
  412. <style lang="less">
  413. .powerLinefitting {
  414. padding: 0 23px;
  415. .powerLinefitting_topAll {
  416. display: flex;
  417. justify-content: space-between;
  418. .powerLinefitting_top {
  419. display: flex;
  420. flex-direction: row;
  421. align-items: center;
  422. margin-top: 10px;
  423. margin-bottom: 10px;
  424. .station {
  425. display: flex;
  426. flex-direction: row;
  427. align-items: center;
  428. font-size: 14px;
  429. font-family: Microsoft YaHei;
  430. font-weight: 400;
  431. color: #b3b3b3;
  432. margin-right: 10px;
  433. margin-left: 10px;
  434. }
  435. .search-input {
  436. margin-left: 10px;
  437. .el-input__inner {
  438. width: 175px;
  439. }
  440. .el-input__suffix {
  441. right: -50px;
  442. }
  443. }
  444. .tabCut {
  445. display: inline-block;
  446. margin: 0 10px;
  447. div {
  448. display: inline-block;
  449. width: 60px;
  450. height: 27px;
  451. border: 1px solid #274934;
  452. text-align: center;
  453. line-height: 25px;
  454. cursor: pointer;
  455. }
  456. div:nth-child(1) {
  457. border-radius: 13px 0px 0px 13px;
  458. }
  459. div:nth-child(2) {
  460. border-radius: 0px 13px 13px 0px;
  461. }
  462. .active {
  463. background-color: rgba(5, 187, 76, 0.9);
  464. color: #fff;
  465. }
  466. }
  467. .but {
  468. display: flex;
  469. flex-direction: row;
  470. align-content: center;
  471. margin-left: 20px;
  472. .buttons:nth-child(1) {
  473. background: rgba(5, 187, 76, 0.6);
  474. border: 1px solid #3b6c53;
  475. border-radius: 13px;
  476. color: #fff;
  477. &:hover {
  478. background: rgba(5, 187, 76, 0.9);
  479. border-radius: 13px;
  480. color: #fff;
  481. }
  482. }
  483. .buttons:nth-child(2) {
  484. background: rgba(67, 81, 107, 0.3);
  485. border: 1px solid #3b6c53;
  486. border-radius: 13px;
  487. font-size: 14px;
  488. color: #b3b3b3;
  489. }
  490. }
  491. }
  492. .selections {
  493. display: flex;
  494. margin-top: 10px;
  495. position: relative;
  496. right: 120px;
  497. .selections_btn {
  498. flex: 0 0 55px;
  499. text-align: center;
  500. height: 33px;
  501. line-height: 33px;
  502. margin-right: 8px;
  503. color: #b9b9b9;
  504. font-size: 1.296vh;
  505. background: fade(#3b6c53, 20);
  506. border: 1px solid fade(#3b6c53, 20);
  507. border-radius: 20px;
  508. &:hover,
  509. &.active {
  510. background: fade(#05bb4c, 80);
  511. border: 1px solid #05bb4c;
  512. color: #fff;
  513. cursor: pointer;
  514. }
  515. }
  516. }
  517. }
  518. .powerLinefitting_title {
  519. padding-left: 10px;
  520. .leftContent {
  521. width: 242px;
  522. height: 41px;
  523. line-height: 41px;
  524. background: url("../../../../assets/imgs/title_left_bg.png");
  525. span {
  526. font-size: 16px;
  527. font-family: Microsoft YaHei;
  528. font-weight: 400;
  529. color: #ffffff;
  530. margin-left: 25px;
  531. }
  532. }
  533. .floatLeft {
  534. float: left;
  535. }
  536. .floatRight {
  537. float: right;
  538. }
  539. .rightContent {
  540. width: 212px;
  541. height: 28px;
  542. margin-top: 13px;
  543. background: url("../../../../assets/imgs/title_right_bg.png");
  544. }
  545. }
  546. .clearfix::after {
  547. content: "";
  548. clear: both;
  549. height: 0;
  550. line-height: 0;
  551. visibility: hidden;
  552. display: block;
  553. }
  554. .clearfix {
  555. zoom: 1;
  556. }
  557. .powerLinefitting_Table {
  558. margin: 0 5px 5px 5px;
  559. padding-bottom: 10px;
  560. .el-table--mini {
  561. margin: 5px;
  562. .el-table__header-wrapper {
  563. tr {
  564. background: rgba(83, 89, 104, 0.3) !important;
  565. th {
  566. vertical-align: top !important;
  567. }
  568. .cell {
  569. color: #b3b3b3;
  570. font-family: MicrosoftYaHei;
  571. font-size: 14px;
  572. }
  573. }
  574. }
  575. .el-table__body-wrapper {
  576. tr {
  577. &:nth-child(2n) {
  578. background: rgba(83, 89, 104, 0.05) !important;
  579. }
  580. .cell {
  581. color: #d8d8d9;
  582. font-family: ArialMT;
  583. font-size: 13px;
  584. height: 25px !important;
  585. }
  586. }
  587. }
  588. }
  589. .historyBtn {
  590. background: #43516b;
  591. border-radius: 15px;
  592. margin-top: 5px;
  593. border: 1px solid #43516b;
  594. span {
  595. color: #fff;
  596. }
  597. }
  598. }
  599. .powerLinefitting_Echarts {
  600. margin-top: 10px;
  601. width: 100%;
  602. background: rgba(0, 0, 0, 0.45);
  603. position: relative;
  604. height: 39px;
  605. // border-bottom: 1px solid rgba(153, 153, 153, 0.5);
  606. font-size: 16px;
  607. font-family: Microsoft YaHei;
  608. font-weight: 400;
  609. color: #ffffff;
  610. .chart-name {
  611. display: flex;
  612. align-items: center;
  613. padding-left: 20px;
  614. position: relative;
  615. height: 39px;
  616. width: 98%;
  617. margin-left: 1%;
  618. border-bottom: 1px solid rgba(153, 153, 153, 0.5);
  619. font-size: 16px;
  620. font-family: Microsoft YaHei;
  621. font-weight: 400;
  622. color: #ffffff;
  623. .point {
  624. width: 6px;
  625. height: 1px;
  626. background-color: #ffffff;
  627. position: absolute;
  628. &.point-left {
  629. left: 0;
  630. }
  631. &.point-right {
  632. right: 0;
  633. }
  634. &.top {
  635. top: -1px;
  636. }
  637. &.bottom {
  638. bottom: -1px;
  639. }
  640. }
  641. }
  642. .fittingEchartSty {
  643. width: 100%;
  644. height: 280px;
  645. background: rgba(0, 0, 0, 0.45);
  646. }
  647. }
  648. .el-overlay {
  649. .el-overlay-dialog {
  650. overflow-y: hidden !important;
  651. .powerLinefittinghistoryModel {
  652. margin-top: 0 !important;
  653. .el-dialog__body {
  654. padding-top: 10px;
  655. }
  656. }
  657. .contrastModal {
  658. .el-dialog__body {
  659. padding-top: 10px;
  660. }
  661. }
  662. }
  663. }
  664. .el-picker__popper .el-date-range-picker__header .el-picker-panel__icon-btn {
  665. color: #fff;
  666. }
  667. .el-picker__popper .el-date-table .in-range div {
  668. background: #43516b;
  669. }
  670. }
  671. </style>