index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. <template>
  2. <div class="parcel-box">
  3. <div class="search">
  4. <div class="search-left">
  5. <el-select
  6. size="mini"
  7. v-model="company"
  8. placeholder="请选择"
  9. @change="companyChanged"
  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="tabClick(val.id)"
  22. :class="[
  23. tabIndex === val.id ? 'active' : '',
  24. displayDetail ? 'disabled' : '',
  25. ]"
  26. v-for="val in tabOptions"
  27. :key="val.id"
  28. >
  29. <span>{{ val.name }}</span>
  30. </div>
  31. </div>
  32. <el-select
  33. size="mini"
  34. v-model="station"
  35. placeholder="请选择"
  36. style="margin-left: 15px"
  37. @change="stationChanged"
  38. >
  39. <el-option
  40. v-for="item in stationOptions"
  41. :key="item.id"
  42. :label="item.aname"
  43. :value="item.id"
  44. >
  45. </el-option>
  46. </el-select>
  47. <el-date-picker
  48. size="mini"
  49. type="year"
  50. v-model="year"
  51. value-format="YYYY"
  52. placeholder="请选择"
  53. style="margin-left: 15px"
  54. popper-class="date-select"
  55. >
  56. </el-date-picker>
  57. <el-button round size="mini" class="searchColor" @click="getDatas"
  58. >搜 索</el-button
  59. >
  60. </div>
  61. </div>
  62. <div
  63. class="parcel-content"
  64. v-loading="loading"
  65. element-loading-background="rgba(4, 12, 11, 0.8)"
  66. >
  67. <!-- <img src="@/assets/imgs/glycfx-bg1.png" alt="" /> -->
  68. <div class="line clearfix">
  69. <div class="leftContent">
  70. <span>{{ selectValue }}</span>
  71. </div>
  72. </div>
  73. <div class="table-wrapper">
  74. <el-table
  75. :data="tableData"
  76. size="mini"
  77. stripe
  78. width="100%"
  79. height="100%"
  80. >
  81. <el-table-column
  82. v-for="(item, index) in tableHead"
  83. :label="item"
  84. :key="index"
  85. header-align="center"
  86. :align="item == '指标名称' ? 'center' : 'right'"
  87. :width="item == '指标名称' ? '200px' : ''"
  88. show-overflow-tooltip
  89. >
  90. <template #default="scope">
  91. <span>
  92. {{
  93. scope.row[index] || scope.row[index] == 0
  94. ? scope.row[index]
  95. : "--"
  96. }}
  97. </span>
  98. </template>
  99. </el-table-column>
  100. </el-table>
  101. </div>
  102. <div class="echarts">
  103. <div class="chart-wrapper">
  104. <BarCharts
  105. :list="list"
  106. width="100%"
  107. height="100%"
  108. :tabIndex="tabIndex"
  109. ></BarCharts>
  110. </div>
  111. </div>
  112. </div>
  113. </div>
  114. </template>
  115. <script>
  116. import BarCharts from "./components/barCharts.vue";
  117. import { companys } from "@/api/curveAnalyse";
  118. import { GetStationByCompany } from "@/api/factoryMonitor/index.js";
  119. import {
  120. getMonthElectricAnalyse,
  121. getMonthElectricAnalyseGf,
  122. } from "@/api/monthlyPerformanceAnalysis.js";
  123. export default {
  124. name: "ElectricAnalyse",
  125. components: {
  126. BarCharts,
  127. },
  128. data() {
  129. return {
  130. loading: false,
  131. list: [],
  132. barList: [],
  133. tableData: [],
  134. tableHead: [
  135. "指标名称",
  136. "一月",
  137. "二月",
  138. "三月",
  139. "四月",
  140. "五月",
  141. "六月",
  142. "七月",
  143. "八月",
  144. "九月",
  145. "十月",
  146. "十一月",
  147. "十二月",
  148. "合计",
  149. ],
  150. company: "",
  151. companyOptions: [],
  152. station: "",
  153. stationOptions: [],
  154. year: "2023",
  155. selectValue: "发电量分析",
  156. headers: [
  157. "计划电量",
  158. "预测电量",
  159. "实发电量",
  160. "当月占比(实发/计划)",
  161. "全年占比(实发/计划)",
  162. "短期功率预测准确率",
  163. ],
  164. headersGf: [
  165. "日照强度(kW/m²)",
  166. "实发电量",
  167. "计划电量",
  168. "计划完成情况(%)",
  169. "可研电量",
  170. "可研完成情况(%)",
  171. "等价发电小时(h)",
  172. ],
  173. tabIndex: -1,
  174. tabOptions: [
  175. { id: -1, name: "风电" },
  176. { id: -2, name: "光伏" },
  177. ],
  178. };
  179. },
  180. watch: {},
  181. created() {
  182. this.initialization();
  183. },
  184. methods: {
  185. tabClick(tab) {
  186. this.tabIndex = tab;
  187. if (tab == -2) {
  188. this.company = "SXJ_KGDL_GFFD_ZGS";
  189. this.station = "";
  190. this.getStation();
  191. } else {
  192. this.company = this.companyOptions[0].id;
  193. this.station = "";
  194. this.getStation();
  195. }
  196. },
  197. initialization() {
  198. companys().then(({ data: res }) => {
  199. if (res.data) {
  200. this.companyOptions = res.data;
  201. this.company = res.data[0].id;
  202. this.getStation();
  203. }
  204. });
  205. },
  206. companyChanged() {
  207. this.station = "";
  208. this.getStation();
  209. },
  210. getStation() {
  211. GetStationByCompany({
  212. companyids: this.company,
  213. type: this.tabIndex,
  214. }).then(({ data: res, code }) => {
  215. if (res.code == 200 && res.data.length) {
  216. this.stationOptions = res.data;
  217. this.station = this.stationOptions[0]?.id || "";
  218. this.getDatas();
  219. } else {
  220. this.tableData = [];
  221. this.list = [];
  222. }
  223. });
  224. },
  225. getDatas() {
  226. this.loading = true;
  227. if (this.tabIndex == -1) {
  228. this.asyncDataFd();
  229. } else {
  230. this.asyncDataGf();
  231. }
  232. },
  233. asyncDataFd() {
  234. getMonthElectricAnalyse({ wpId: this.station, year: this.year }).then(
  235. ({ data, code }) => {
  236. if (code == 200) {
  237. //合计列
  238. let hj = [
  239. data.bnjhdlhj,
  240. data.rfdlychj,
  241. data.bnsjdlhj,
  242. null,
  243. data.qnzbhj + "%",
  244. data.dqzqlhj + "%",
  245. ];
  246. //处理纵向表格数据
  247. let resData = JSON.parse(JSON.stringify(data.value));
  248. // 数组按矩阵思路, 变成转置矩阵
  249. let matrixData = resData.map((row) => {
  250. let arr = [];
  251. for (let key in row) {
  252. if (key != "hours") {
  253. if (key.includes("zb") || key.includes("zql")) {
  254. arr.push(row[key] ? row[key] + "%" : row[key]);
  255. } else {
  256. arr.push(row[key]);
  257. }
  258. }
  259. }
  260. return arr;
  261. });
  262. // 加入标题拼接最终的数据
  263. this.tableData = matrixData[0].map((col, i) => {
  264. let newArr = new Array(
  265. this.tableHead.length - matrixData.length - 2
  266. ).fill(null);
  267. let array = [
  268. this.headers[i],
  269. ...matrixData.map((row) => {
  270. return row[i];
  271. }),
  272. ...newArr,
  273. hj[i],
  274. ];
  275. return array;
  276. });
  277. //处理图表数据
  278. let list = [
  279. {
  280. name: "计划电量",
  281. data: resData.map((ele) => ele.jhdl),
  282. color: "#4B55AE",
  283. },
  284. {
  285. name: "预测电量",
  286. data: resData.map((ele) => ele.rfdlyc),
  287. color: "#FF8300",
  288. },
  289. {
  290. name: "实发电量",
  291. data: resData.map((ele) => ele.sjdl),
  292. color: "#05BB4C",
  293. },
  294. ];
  295. this.list = list;
  296. }
  297. this.loading = false;
  298. }
  299. );
  300. },
  301. asyncDataGf() {
  302. getMonthElectricAnalyseGf({ wpId: this.station, year: this.year }).then(
  303. ({ data, code }) => {
  304. if (code == 200) {
  305. //合计列
  306. let hj = [
  307. data.rzqdhj,
  308. data.sjdlhj,
  309. data.jhdlhj,
  310. data.wcqkhj + "%",
  311. data.kydlhj,
  312. data.kywcqkhj + "%",
  313. data.dxxsshj,
  314. ];
  315. //处理纵向表格数据
  316. let resData = JSON.parse(JSON.stringify(data.value));
  317. // 数组按矩阵思路, 变成转置矩阵
  318. let matrixData = resData.map((row) => {
  319. let arr = [];
  320. for (let key in row) {
  321. if (key != "hours") {
  322. if (key == "wcqk" || key == "kywcqk") {
  323. arr.push(row[key] ? row[key] + "%" : row[key]);
  324. } else {
  325. arr.push(row[key]);
  326. }
  327. }
  328. }
  329. return arr;
  330. });
  331. // 加入标题拼接最终的数据
  332. this.tableData = matrixData[0].map((col, i) => {
  333. let newArr = new Array(
  334. this.tableHead.length - matrixData.length - 2
  335. ).fill(null);
  336. let array = [
  337. this.headersGf[i],
  338. ...matrixData.map((row) => {
  339. return row[i];
  340. }),
  341. ...newArr,
  342. hj[i],
  343. ];
  344. return array;
  345. });
  346. //处理图表数据
  347. let list = [
  348. {
  349. name: "计划电量",
  350. data: resData.map((ele) => ele.jhdl),
  351. color: "#4B55AE",
  352. },
  353. {
  354. name: "实发电量",
  355. data: resData.map((ele) => ele.sjdl),
  356. color: "#05BB4C",
  357. },
  358. {
  359. name: "可研电量",
  360. data: resData.map((ele) => ele.sjdl),
  361. color: "#21a4f7",
  362. },
  363. {
  364. name: "日照强度",
  365. data: resData.map((ele) => ele.rzqd),
  366. color: "#FF8300",
  367. },
  368. ];
  369. this.list = list;
  370. }
  371. this.loading = false;
  372. }
  373. );
  374. },
  375. },
  376. };
  377. </script>
  378. <style lang="less" scoped>
  379. .parcel-box {
  380. padding: 0 20px;
  381. box-sizing: border-box;
  382. width: 100%;
  383. height: 100%;
  384. .search {
  385. display: flex;
  386. flex-direction: row;
  387. padding: 15px 0;
  388. align-items: center;
  389. justify-content: space-between;
  390. .search-left {
  391. display: flex;
  392. flex-direction: row;
  393. align-items: center;
  394. .tabCut {
  395. display: inline-block;
  396. margin: 0 10px;
  397. div {
  398. display: inline-block;
  399. width: 60px;
  400. height: 27px;
  401. border: 1px solid #274934;
  402. text-align: center;
  403. line-height: 25px;
  404. cursor: pointer;
  405. }
  406. div:nth-child(1) {
  407. border-radius: 13px 0px 0px 13px;
  408. border-right-width: 0;
  409. }
  410. div:nth-child(2) {
  411. border-radius: 0px 13px 13px 0px;
  412. }
  413. .active {
  414. background-color: rgba(5, 187, 76, 0.9);
  415. color: #fff;
  416. }
  417. .disabled {
  418. cursor: not-allowed;
  419. pointer-events: none;
  420. }
  421. }
  422. }
  423. .search-right {
  424. position: relative;
  425. .select-back {
  426. position: absolute;
  427. right: 5px;
  428. top: 0px;
  429. z-index: 0;
  430. }
  431. .title-select {
  432. z-index: 2;
  433. }
  434. }
  435. button {
  436. margin-left: 10px;
  437. background: rgba(67, 81, 107, 0.3);
  438. border: 1px solid #274934;
  439. color: #b3b3b3;
  440. }
  441. .searchColor {
  442. background-color: rgba(5, 187, 76, 0.2);
  443. border: 1px solid #3b6c53;
  444. color: #b3b3b3;
  445. font-size: 14px;
  446. &:hover {
  447. background-color: rgba(5, 187, 76, 0.5);
  448. color: #ffffff;
  449. }
  450. }
  451. }
  452. .parcel-content {
  453. width: 100%;
  454. height: calc(100% - 88px);
  455. // position: relative;
  456. background: url("~@/assets/imgs/glycfx-bg1.png") no-repeat;
  457. background-size: 100% 100%;
  458. background-position: center;
  459. img {
  460. position: absolute;
  461. top: 0;
  462. left: 0;
  463. width: 100%;
  464. height: 100%;
  465. }
  466. .line {
  467. .leftContent {
  468. width: 242px;
  469. height: 45px;
  470. line-height: 45px;
  471. background: url("~@/assets/imgs/title_left_bg1.png") no-repeat;
  472. span {
  473. font-size: 16px;
  474. font-family: Microsoft YaHei;
  475. font-weight: 400;
  476. color: #05bb4c;
  477. margin-left: 25px;
  478. }
  479. }
  480. }
  481. .echarts {
  482. height: calc(100% - 305px - 45px);
  483. padding: 0 20px;
  484. .chart-wrapper {
  485. height: 100%;
  486. width: 100%;
  487. }
  488. }
  489. .table-wrapper {
  490. height: 305px;
  491. width: 100%;
  492. padding: 0 20px;
  493. padding-top: 10px;
  494. }
  495. }
  496. }
  497. </style>