index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. <template>
  2. <div class="dataAnalysisWindAna" :class="!theme ? 'themeDark' : 'themeLight'">
  3. <div class="dataAnalysisWindAnaMain">
  4. <div class="main_top">
  5. <p class="topPsty">损失电量分析</p>
  6. </div>
  7. <div class="main">
  8. <div class="treeDataMain">
  9. <tree-cop
  10. ref="treeCopRef"
  11. :data="treeData"
  12. @checkChange="funTreeCheckChange"
  13. :show-checkbox="true"
  14. :height="treeHeight"
  15. @currentChange="funCurrentChange"
  16. @refresh="funGetTree"
  17. ></tree-cop>
  18. </div>
  19. <div class="excelDataMain">
  20. <excel-cop
  21. :checkIds="excelCheckIds"
  22. :showCheckbox="excelCheckboxShow"
  23. :data="excelList"
  24. :theme="theme"
  25. :height="excelHeight"
  26. @excelChange="funExcelChange"
  27. @checkChange="funExcelCheckChange"
  28. >
  29. </excel-cop>
  30. </div>
  31. <div class="tableDataMain">
  32. <div class="px-[10px] shadow rounded-[6px] shadow-blue-500">
  33. <el-tabs v-model="activeTab">
  34. <el-tab-pane label="图表展示" name="1"> </el-tab-pane>
  35. <el-tab-pane label="表格数据" name="2"> </el-tab-pane>
  36. <table-cop
  37. class=""
  38. v-show="activeTab === '2'"
  39. :data="tableData"
  40. :showSummary="true"
  41. :summaryMethod="funSummary"
  42. :column="tableColumn"
  43. :loading="tableLoading"
  44. :theme="theme"
  45. :height="tableHeight"
  46. :tableId="tableShowId"
  47. :tableName="tableName"
  48. ></table-cop>
  49. <div
  50. v-show="activeTab === '1'"
  51. :style="{
  52. height:
  53. typeof tableHeight === 'string'
  54. ? tableHeight
  55. : tableHeight + 'px',
  56. }"
  57. class="p-[10px]"
  58. >
  59. <bar-line-chart-cop
  60. v-show="lineData.length"
  61. :height="tableHeight"
  62. :bardata="barData"
  63. :lineData="lineData"
  64. :color="barColor"
  65. lineName="理论发电量"
  66. ></bar-line-chart-cop>
  67. <el-empty
  68. v-show="!lineData.length"
  69. description="请选择条件"
  70. ></el-empty>
  71. </div>
  72. </el-tabs>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </template>
  79. <script setup name="prepare">
  80. import tableCop from "@/components/generatingCapacityComponent/table.vue";
  81. import excelCop from "@/components/generatingCapacityComponent/excel.vue";
  82. import treeCop from "@/components/generatingCapacityComponent/tree.vue";
  83. import barLineChartCop from "./components/barLineChart.vue";
  84. import { ElMessage } from "element-plus";
  85. import { onMounted, ref, onActivated, watch } from "vue";
  86. import { useStore } from "vuex";
  87. import httpRequest from "@/utils/request.js";
  88. import jsonData from "./components/data.json";
  89. /**配置参数 */
  90. const treeHeight = ref(window.innerHeight - 111 + "px"); //tree高度
  91. const excelHeight = ref(window.innerHeight - 111 + "px"); //excel高度
  92. const tableHeight = ref(window.innerHeight - 175 + "px");
  93. /**table 开始 */
  94. const tableShowId = ref("");
  95. const tableName = ref("损失电量分析");
  96. const tableColumn = ref([]);
  97. const tableLoading = ref(false);
  98. const tableData = ref([]);
  99. const funSummary = ({ columns, data }) => {
  100. const sums = [];
  101. columns.forEach((column, index) => {
  102. if (index === 0) {
  103. sums[index] = "合计";
  104. return;
  105. }
  106. const values = data.map((item) => Number(item[column.property]));
  107. if (!values.every((value) => Number.isNaN(value))) {
  108. sums[index] = values.reduce((prev, curr) => {
  109. const value = Number(curr);
  110. if (!Number.isNaN(value)) {
  111. return Number((prev + curr).toFixed(2));
  112. } else {
  113. return Number(prev.toFixed(2));
  114. }
  115. }, 0);
  116. } else {
  117. sums[index] = "--";
  118. }
  119. if (["speed", "fnlly"].includes(column.property)) {
  120. if (!Number.isNaN(sums[index])) {
  121. sums[index] = Number((sums[index] / data.length).toFixed(2));
  122. }
  123. }
  124. });
  125. return sums;
  126. };
  127. const funSubmit = async () => {
  128. if (!excelCheckIds.value.length) {
  129. ElMessage.error("请勾选要展现的项");
  130. return false;
  131. }
  132. tableLoading.value = true;
  133. tableData.value = [];
  134. tableShowId.value = "";
  135. barData.value = {
  136. area: [],
  137. legend: [],
  138. data: [],
  139. };
  140. lineData.value = [];
  141. const res = await httpRequest.get("/fjjxb/five/loss/cal", {
  142. params: {
  143. ids: excelCheckIds.value.join(),
  144. },
  145. });
  146. if (res.code !== 200 || !res.data.title) {
  147. tableLoading.value = false;
  148. return false;
  149. }
  150. ElMessage.success(res.msg);
  151. tableColumn.value = res.data.title.map((o) => {
  152. return {
  153. prop: o.key,
  154. label: o.des,
  155. width: o.des === "时间" ? 100 : 80,
  156. };
  157. });
  158. tableData.value = res.data.data;
  159. const name = [],
  160. data = [],
  161. llfdl = [],
  162. legend = [
  163. {
  164. name: "实际电量",
  165. icon: "rect",
  166. },
  167. {
  168. name: "计划检修损失",
  169. icon: "rect",
  170. },
  171. {
  172. name: "非计划检修损失",
  173. icon: "rect",
  174. },
  175. {
  176. name: "限电损失",
  177. icon: "rect",
  178. },
  179. {
  180. name: "受累损失",
  181. icon: "rect",
  182. },
  183. {
  184. name: "性能损失",
  185. icon: "rect",
  186. },
  187. {
  188. name: "理论发电量",
  189. icon: "circle",
  190. },
  191. ],
  192. // legend = [
  193. // "实际电量",
  194. // "计划检修损失",
  195. // "非计划检修损失",
  196. // "限电损失",
  197. // "受累损失",
  198. // "性能损失",
  199. // "理论发电量"
  200. // ],
  201. data2 = []; //项目列表
  202. // if (params.station) {
  203. // let arr = [];
  204. // let hj = res.data.data.pop();
  205. // res.data.data.forEach((ele, index) => {
  206. // arr[ele.id.split('_')[1] - 1] = ele
  207. // })
  208. // arr.push(hj);
  209. // res.data.data = arr;
  210. // }
  211. res.data.data.forEach((item, index) => {
  212. name.push(item.name);
  213. data.push([item.sjfdl, item.jhjx, item.fjhjx, item.xd, item.sl, item.xn]);
  214. llfdl.push(item.llfdl);
  215. data2.push({
  216. index: index + 1,
  217. name: item.name,
  218. llfdl: item.llfdl,
  219. sjfdl: item.sjfdl,
  220. speed: item.speed,
  221. fjhjx: item.fjhjx,
  222. jhjx: item.jhjx,
  223. sl: item.sl,
  224. xd: item.xd,
  225. xn: item.xn,
  226. fnlly: item.fnlly,
  227. is_light: false,
  228. });
  229. });
  230. if (data.length > 0) {
  231. let arr1 = [];
  232. const length = data[0].length;
  233. for (var i = 0; i < length; i++) {
  234. let arr2 = [];
  235. data.forEach((ele) => {
  236. arr2.push(ele[i]);
  237. });
  238. arr1.push(arr2);
  239. }
  240. lineData.value = llfdl;
  241. barData.value = {
  242. area: name,
  243. legend: legend,
  244. data: arr1,
  245. };
  246. }
  247. tableLoading.value = false;
  248. tableShowId.value = "1";
  249. activeTab.value = "1";
  250. };
  251. /**barlineChart 开始 */
  252. const barData = ref({
  253. area: [],
  254. legend: [],
  255. data: [],
  256. });
  257. const lineData = ref([]);
  258. const barColor = [
  259. "#4b55ae",
  260. "#e17e23",
  261. "#ba3237",
  262. "#c531c7",
  263. "rgb(63,177,227)",
  264. "#05bb4c",
  265. ];
  266. /**tabs */
  267. const activeTab = ref("1");
  268. /**excel 开始 */
  269. const excelCheckboxShow = ref(false);
  270. const excelType = ref("");
  271. const treeCopRef = ref(); //treeCop ref
  272. const excelCheckIds = ref([]);
  273. const excelList = ref([]);
  274. const funExcelChange = async (obj) => {
  275. //点击excel项时
  276. return false;
  277. };
  278. const funExcelCheckChange = ({ checkArr, data }) => {
  279. //bug
  280. excelCheckIds.value = checkArr;
  281. funSubmit();
  282. };
  283. /**prepare tree 开始 */
  284. const treeData = ref([]);
  285. const actTreeNode = ref(null); //当前激活的treeNode
  286. const funRepeatMap = (arr) => {
  287. return arr.map((o) => {
  288. if (o.children) {
  289. const findIndex = o.children.findIndex((p) => !!p.type);
  290. if (findIndex !== -1) {
  291. o.childs = o.children;
  292. o.children = [];
  293. if (!actTreeNode.value) {
  294. //判断当且仅有process获取tree时 赋值
  295. actTreeNode.value = o;
  296. }
  297. }
  298. }
  299. return {
  300. ...o,
  301. children: o.children ? funRepeatMap(o.children) : [],
  302. };
  303. });
  304. };
  305. const funGetTree = async () => {
  306. actTreeNode.value = null;
  307. const res = await httpRequest.get("/power/prepare/tree");
  308. treeData.value = funRepeatMap(res.data);
  309. excelList.value = [];
  310. if (actTreeNode.value) {
  311. funCurrentChange({
  312. current: actTreeNode.value,
  313. currentNode: null,
  314. });
  315. if (treeCopRef.value) {
  316. treeCopRef.value.$refs.tree.setCheckedKeys([actTreeNode.value.id]);
  317. excelCheckIds.value = actTreeNode.value.childs.map((o) => o.id);
  318. funSubmit();
  319. }
  320. }
  321. };
  322. const funCurrentChange = ({ current, currentNode }) => {
  323. excelCheckboxShow.value = true;
  324. if (current.childs) {
  325. excelList.value = current.childs.map((o) => {
  326. return {
  327. id: o.id,
  328. interval: o.interval,
  329. path: o.path,
  330. prepareid: o.prepareid,
  331. station: o.station,
  332. time: o.time,
  333. type: o.type,
  334. windturbine: o.windturbine,
  335. name: o.path.substring(
  336. o.path.indexOf(o.station + "_") + (o.station + "_").length
  337. ),
  338. };
  339. });
  340. } else {
  341. excelList.value = [];
  342. }
  343. };
  344. const funTreeCheckChange = ({
  345. current,
  346. checkedNodes,
  347. checkedKeys,
  348. halfCheckedNodes,
  349. halfCheckedKeys,
  350. }) => {
  351. //tree change -> excel change
  352. funCurrentChange({
  353. current,
  354. currentNode: "",
  355. });
  356. const checkIds = [];
  357. if (checkedNodes.checkedNodes.length) {
  358. let checkArr = checkedNodes.checkedNodes;
  359. checkArr.forEach((it) => {
  360. if (it.childs && it.childs.length) {
  361. it.childs.forEach((iv) => {
  362. checkIds.push(iv.id);
  363. });
  364. }
  365. });
  366. }
  367. excelCheckIds.value = checkIds;
  368. funSubmit();
  369. };
  370. /**created */
  371. const theme = ref(null);
  372. const echartsTheme = ref("");
  373. const store = useStore();
  374. watch(
  375. () => store.state.theme,
  376. (newVal, oldVal) => {
  377. theme.value = newVal;
  378. echartsTheme.value = !newVal ? "dark" : "";
  379. funGetTree();
  380. },
  381. {
  382. deep: true,
  383. }
  384. );
  385. const initPageData = () => {
  386. actTreeNode.value = null;
  387. treeData.value = funRepeatMap(JSON.parse(JSON.stringify(jsonData.treeData)));
  388. excelList.value = [];
  389. if (actTreeNode.value) {
  390. if (actTreeNode.value.childs) {
  391. excelList.value = actTreeNode.value.childs.map((o) => {
  392. return {
  393. id: o.id,
  394. interval: o.interval,
  395. path: o.path,
  396. prepareid: o.prepareid,
  397. station: o.station,
  398. time: o.time,
  399. type: o.type,
  400. windturbine: o.windturbine,
  401. isCheck: false,
  402. name: o.path.substring(
  403. o.path.indexOf(o.station + "_") + (o.station + "_").length
  404. ),
  405. };
  406. });
  407. } else {
  408. excelList.value = [];
  409. }
  410. if (treeCopRef.value) {
  411. treeCopRef.value.$refs.tree.setCheckedKeys([actTreeNode.value.id]);
  412. excelCheckIds.value = actTreeNode.value.childs.map((o) => o.id);
  413. tableLoading.value = true;
  414. tableData.value = [];
  415. tableShowId.value = "";
  416. barData.value = {
  417. area: [],
  418. legend: [],
  419. data: [],
  420. };
  421. lineData.value = [];
  422. tableColumn.value = jsonData.tableData.title.map((o) => {
  423. return {
  424. prop: o.key,
  425. label: o.des,
  426. width: o.des === "时间" ? 100 : 80,
  427. };
  428. });
  429. tableData.value = jsonData.tableData.data;
  430. const name = [],
  431. data = [],
  432. llfdl = [],
  433. legend = [
  434. {
  435. name: "实际电量",
  436. icon: "rect",
  437. },
  438. {
  439. name: "计划检修损失",
  440. icon: "rect",
  441. },
  442. {
  443. name: "非计划检修损失",
  444. icon: "rect",
  445. },
  446. {
  447. name: "限电损失",
  448. icon: "rect",
  449. },
  450. {
  451. name: "受累损失",
  452. icon: "rect",
  453. },
  454. {
  455. name: "性能损失",
  456. icon: "rect",
  457. },
  458. {
  459. name: "理论发电量",
  460. icon: "circle",
  461. },
  462. ],
  463. data2 = []; //项目列表
  464. jsonData.tableData.data.forEach((item, index) => {
  465. name.push(item.name);
  466. data.push([
  467. item.sjfdl,
  468. item.jhjx,
  469. item.fjhjx,
  470. item.xd,
  471. item.sl,
  472. item.xn,
  473. ]);
  474. llfdl.push(item.llfdl);
  475. data2.push({
  476. index: index + 1,
  477. name: item.name,
  478. llfdl: item.llfdl,
  479. sjfdl: item.sjfdl,
  480. speed: item.speed,
  481. fjhjx: item.fjhjx,
  482. jhjx: item.jhjx,
  483. sl: item.sl,
  484. xd: item.xd,
  485. xn: item.xn,
  486. fnlly: item.fnlly,
  487. is_light: false,
  488. });
  489. });
  490. if (data.length > 0) {
  491. let arr1 = [];
  492. const length = data[0].length;
  493. for (var i = 0; i < length; i++) {
  494. let arr2 = [];
  495. data.forEach((ele) => {
  496. arr2.push(ele[i]);
  497. });
  498. arr1.push(arr2);
  499. }
  500. lineData.value = llfdl;
  501. barData.value = {
  502. area: name,
  503. legend: legend,
  504. data: arr1,
  505. };
  506. }
  507. tableLoading.value = false;
  508. tableShowId.value = "1";
  509. activeTab.value = "1";
  510. }
  511. }
  512. };
  513. /**mounted */
  514. onMounted(() => {
  515. initPageData();
  516. funGetTree();
  517. theme.value = store.state.theme;
  518. echartsTheme.value = !theme.value ? "dark" : "";
  519. tableHeight.value = window.innerHeight - 175 + "px";
  520. excelHeight.value = window.innerHeight - 111 + "px";
  521. treeHeight.value = window.innerHeight - 111 + "px";
  522. window.addEventListener("resize", () => {
  523. tableHeight.value = window.innerHeight - 175 + "px";
  524. excelHeight.value = window.innerHeight - 111 + "px";
  525. treeHeight.value = window.innerHeight - 111 + "px";
  526. });
  527. });
  528. /**activated */
  529. onActivated(() => {
  530. // funGetTree()
  531. });
  532. </script>
  533. <style lang="less" scoped>
  534. .dataAnalysisWindAna {
  535. height: 100%;
  536. .dataAnalysisWindAnaMain {
  537. height: 100%;
  538. .main_top {
  539. height: 40px;
  540. display: flex;
  541. align-items: center;
  542. .topPsty {
  543. position: relative;
  544. top: 5px;
  545. padding: 7px 20px;
  546. font-size: 12px;
  547. font-weight: 600;
  548. margin-left: 10px;
  549. border-radius: 3px;
  550. }
  551. }
  552. .main {
  553. display: flex;
  554. width: 100%;
  555. .treeDataMain,
  556. .excelDataMain,
  557. .tableDataMain {
  558. border-radius: 10px;
  559. }
  560. .treeDataMain {
  561. margin-right: 10px;
  562. padding: 10px 0 10px 10px;
  563. width: calc(19% - 20px);
  564. }
  565. .excelDataMain {
  566. margin-right: 10px;
  567. padding: 10px 0 10px 10px;
  568. width: calc(15% - 20px);
  569. }
  570. .tableDataMain {
  571. padding: 10px;
  572. width: calc(66% - 20px);
  573. position: relative;
  574. .butten_com {
  575. position: absolute;
  576. right: 20px;
  577. z-index: 111111;
  578. }
  579. }
  580. }
  581. }
  582. }
  583. .themeDark {
  584. .dataAnalysisWindAnaMain {
  585. .main_top {
  586. .topPsty {
  587. color: #1c99ff;
  588. background: #1e2126;
  589. }
  590. }
  591. .main {
  592. background: #13171e;
  593. .treeDataMain {
  594. background: transparent;
  595. }
  596. .excelDataMain {
  597. background: #313233;
  598. }
  599. .tableDataMain {
  600. margin-top: 5px;
  601. background: #212223;
  602. }
  603. }
  604. }
  605. }
  606. .themeLight {
  607. padding: 0;
  608. .dataAnalysisWindAnaMain {
  609. .main_top {
  610. .topPsty {
  611. color: #2778ff;
  612. background: #ffffff;
  613. }
  614. }
  615. .main {
  616. background: #e6e8f2;
  617. .treeDataMain {
  618. background: transparent;
  619. }
  620. .excelDataMain {
  621. background: #f4f6fb;
  622. }
  623. .tableDataMain {
  624. background: #fff;
  625. margin-top: 5px;
  626. }
  627. }
  628. }
  629. }
  630. </style>