1
0

index.vue 16 KB

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