index.vue 13 KB

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