index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. <template>
  2. <div class="data-overview">
  3. <el-row :gutter="15" class="home-card-one mb15">
  4. <el-col
  5. :xs="24"
  6. :sm="12"
  7. :md="12"
  8. :lg="6"
  9. :xl="6"
  10. v-for="(v, k) in dataOne"
  11. :key="k"
  12. :class="{ 'home-media home-media-lg': k > 1, 'home-media-sm': k === 1 }"
  13. >
  14. <div class="home-card-item">
  15. <div class="item-header">
  16. <img :src="isIsDark ? v.iconDark : v.icon" alt="" />
  17. <span>{{ v.title }}</span>
  18. </div>
  19. <div class="item-content w100" :class="` home-one-animation${k}`">
  20. <p>
  21. <span class="text-no-wrap">{{ v.contentTitle1 }}</span>
  22. <span>{{ v.val1 }} {{ unitMap[v.contentTitle1] }}</span>
  23. </p>
  24. <p>
  25. <span class="text-no-wrap">{{ v.contentTitle2 }}</span>
  26. <span
  27. >{{ v.val2 }}
  28. {{ unitMap[v.title + ':' + v.contentTitle2] ? unitMap[v.title + ':' + v.contentTitle2] : unitMap[v.contentTitle2] }}</span
  29. >
  30. </p>
  31. <p style="height: 30px">
  32. <template v-if="v.contentTitle3">
  33. <span class="text-no-wrap">{{ v.contentTitle3 || ' ' }}</span>
  34. <span
  35. >{{ v.val3 || ' ' }}
  36. {{ unitMap[v.title + ':' + v.contentTitle3] ? unitMap[v.title + ':' + v.contentTitle3] : unitMap[v.contentTitle3] }}</span
  37. >
  38. </template>
  39. </p>
  40. </div>
  41. </div>
  42. </el-col>
  43. </el-row>
  44. <el-row :gutter="15" class="home-card-two mb15">
  45. <div class="home-card-item" style="height: auto">
  46. <div class="home-card-item-title">总耗热</div>
  47. <div style="height: 200px" ref="homeLineRef1"></div>
  48. </div>
  49. </el-row>
  50. <el-row :gutter="15" class="home-card-two mb15">
  51. <div class="home-card-item" style="height: auto">
  52. <div class="home-card-item-title">总失水量</div>
  53. <div style="height: 200px" ref="homeLineRef3"></div>
  54. </div>
  55. </el-row>
  56. <el-row :gutter="15" class="home-card-two mb15">
  57. <div class="home-card-item" style="height: auto">
  58. <div class="home-card-item-title">平均供热负荷</div>
  59. <div style="height: 200px" ref="homeLineRef4"></div>
  60. </div>
  61. </el-row>
  62. </div>
  63. </template>
  64. <script lang="ts">
  65. import { toRefs, reactive, defineComponent, onMounted, ref, watch, nextTick, onActivated } from 'vue';
  66. import * as echarts from 'echarts';
  67. import { useStore } from '/@/store/index';
  68. import apiDatahub from '/@/api/datahub';
  69. import ele from '/@/assets/img/ele.svg';
  70. import ele1 from '/@/assets/img/ele1.svg';
  71. import fire from '/@/assets/img/fire.svg';
  72. import fire1 from '/@/assets/img/fire1.svg';
  73. import map from '/@/assets/img/map.svg';
  74. import map1 from '/@/assets/img/map1.svg';
  75. import water from '/@/assets/img/water.svg';
  76. import water1 from '/@/assets/img/water1.svg';
  77. import api from '/@/api/datahub';
  78. let global: any = {
  79. homeChartOne: null,
  80. homeChartTwo: null,
  81. homeCharThree: null,
  82. homeCharFour: null,
  83. dispose: [null, '', undefined],
  84. };
  85. export default defineComponent({
  86. name: 'heating-home',
  87. setup() {
  88. const tabName = ref('homeLineRef1');
  89. const homeLineRef1 = ref();
  90. const homeLineRef3 = ref();
  91. const homeLineRef4 = ref();
  92. const homePieRef = ref();
  93. const homeBarRef = ref();
  94. const homeFourBarRef = ref();
  95. const unitMap = ref<any>({});
  96. const store = useStore();
  97. // 统计信息的单位的字典
  98. apiDatahub.template.getDictData({ DictType: 'overview_unit' }).then((res: any) => {
  99. res.values.forEach((v: any) => {
  100. unitMap.value[v.value] = v.key;
  101. });
  102. });
  103. const state = reactive({
  104. checkList: ['一网供水温度'],
  105. rangeValue: 10,
  106. isIsDark: false,
  107. dataOne: [
  108. {
  109. icon: map,
  110. iconDark: map1,
  111. title: '供热面积',
  112. contentTitle1: '联网面积',
  113. val1: '',
  114. contentTitle2: '实供面积',
  115. val2: '',
  116. contentTitle3: '供热率',
  117. val3: '',
  118. },
  119. {
  120. icon: fire,
  121. iconDark: fire1,
  122. title: '热量',
  123. contentTitle1: '总耗热',
  124. val1: '',
  125. contentTitle2: '总单耗',
  126. val2: '',
  127. },
  128. {
  129. icon: ele,
  130. iconDark: ele1,
  131. title: '负荷',
  132. contentTitle1: '供热负荷',
  133. val1: '0',
  134. contentTitle2: '平均供热负荷',
  135. val2: '0',
  136. },
  137. {
  138. icon: water,
  139. iconDark: water1,
  140. title: '水量',
  141. contentTitle1: '总耗水',
  142. val1: '',
  143. contentTitle2: '小时补水量',
  144. val2: '',
  145. },
  146. ],
  147. myCharts: [],
  148. charts: {
  149. theme: '',
  150. bgColor: '',
  151. color: '#303133',
  152. },
  153. statisticsChartXAxisData: [],
  154. inTemperature: [],
  155. outTemperature: [],
  156. diffTemperature: [],
  157. chartXAxisData: [],
  158. flowLossData: [],
  159. elctricConsumptionData: [],
  160. unitConsumptionData: [],
  161. heatDemandData: [],
  162. pieData: [],
  163. pieType: '1',
  164. pressureXAxisData: [],
  165. inPressureData: [],
  166. outPressureData: [],
  167. diffPressureData: [],
  168. });
  169. // 获取顶部总数据
  170. const getStatisticsTotalData = () => {
  171. api.statistics.getStatisticsOverview({ queryType: 'num' }).then((res: any) => {
  172. const { flowLoss, flowLossTotal, forRealArea, heatingArea, unitConsumption, unitConsumptionTotal, heatRate, heatDemandAvg, heatDemand } =
  173. res.data;
  174. state.dataOne[0].val1 = heatingArea;
  175. state.dataOne[0].val2 = forRealArea;
  176. state.dataOne[0].val3 = heatRate;
  177. state.dataOne[1].val1 = unitConsumptionTotal;
  178. state.dataOne[1].val2 = unitConsumption;
  179. state.dataOne[2].val1 = heatDemand;
  180. state.dataOne[2].val2 = heatDemandAvg;
  181. state.dataOne[3].val1 = flowLossTotal;
  182. state.dataOne[3].val2 = flowLoss;
  183. });
  184. };
  185. // 获取热网总能耗数据
  186. const getStatisticsLineChartData = () => {
  187. if (!state.rangeValue) return;
  188. api.statistics.getStatisticsOverview({ queryType: 'energy' }).then((res: any) => {
  189. const { flowLoss, elctricConsumption, unitConsumption, heatDemand } = res.data;
  190. // calorie:总热耗 electric:总电耗 water:总失水量 heatDemand: 供热负荷
  191. state.chartXAxisData = flowLoss.map((item: any) => item.date);
  192. state.flowLossData = flowLoss.map((item: any) => item.total);
  193. state.unitConsumptionData = unitConsumption.map((item: any) => item.total);
  194. state.heatDemandData = heatDemand.map((item: any) => item.total);
  195. if (state.rangeValue == 10) return;
  196. nextTick(() => {
  197. initLineChart('homeLineRef1');
  198. initLineChart('homeLineRef3');
  199. initLineChart('homeLineRef4');
  200. });
  201. });
  202. };
  203. // 折线图
  204. const initLineChart = (ref: string) => {
  205. if (!global.dispose.some((b: any) => b === global.homeCharThree)) global.homeCharThree.dispose();
  206. let dom: any;
  207. let data: any;
  208. let unit: any;
  209. // 总耗热:GJ
  210. // 日失水量:T
  211. // 平均供热负荷: W/m²
  212. if (ref === 'homeLineRef1') {
  213. dom = homeLineRef1.value;
  214. data = state.unitConsumptionData;
  215. unit = 'GJ';
  216. } else if (ref === 'homeLineRef3') {
  217. dom = homeLineRef3.value;
  218. data = state.flowLossData;
  219. unit = 'T';
  220. } else {
  221. dom = homeLineRef4.value;
  222. data = state.heatDemandData;
  223. unit = 'W/m²';
  224. }
  225. const chart = <any>echarts.init(dom, state.charts.theme);
  226. const common = {
  227. type: 'line',
  228. smooth: true,
  229. showSymbol: true,
  230. symbolSize: 12,
  231. yAxisIndex: 0,
  232. };
  233. const option = {
  234. backgroundColor: state.charts.bgColor,
  235. tooltip: { trigger: 'axis' },
  236. grid: { top: 30, right: 40, bottom: 30, left: 25, containLabel: true },
  237. xAxis: [
  238. {
  239. type: 'category',
  240. data: state.chartXAxisData,
  241. boundaryGap: true,
  242. axisTick: { show: false },
  243. },
  244. ],
  245. yAxis: [
  246. {
  247. type: 'value',
  248. name: unit,
  249. },
  250. ],
  251. dataZoom: [
  252. {
  253. type: 'inside',
  254. start: 0,
  255. end: 30,
  256. },
  257. {
  258. start: 0,
  259. end: 30,
  260. },
  261. ],
  262. series: [
  263. {
  264. ...common,
  265. data,
  266. },
  267. ],
  268. };
  269. chart.setOption(option);
  270. };
  271. // 批量设置 echarts resize
  272. const initEchartsResizeFun = () => {
  273. nextTick(() => {
  274. for (let i = 0; i < state.myCharts.length; i++) {
  275. setTimeout(() => {
  276. (<any>state.myCharts[i]).resize();
  277. }, i * 1000);
  278. }
  279. });
  280. };
  281. // 批量设置 echarts resize
  282. const initEchartsResize = () => {
  283. window.addEventListener('resize', initEchartsResizeFun);
  284. };
  285. // 页面加载时
  286. onMounted(() => {
  287. initEchartsResize();
  288. getStatisticsTotalData();
  289. getStatisticsLineChartData();
  290. // 获取布局配置信息
  291. state.isIsDark = store.state.themeConfig.themeConfig.isIsDark;
  292. });
  293. // 由于页面缓存原因,keep-alive
  294. onActivated(() => {
  295. initEchartsResizeFun();
  296. });
  297. // 监听 vuex 中的 tagsview 开启全屏变化,重新 resize 图表,防止不出现/大小不变等
  298. watch(
  299. () => store.state.tagsViewRoutes.isTagsViewCurrenFull,
  300. () => {
  301. initEchartsResizeFun();
  302. }
  303. );
  304. // 监听 vuex 中是否开启深色主题
  305. watch(
  306. () => store.state.themeConfig.themeConfig.isIsDark,
  307. () => {
  308. state.isIsDark = store.state.themeConfig.themeConfig.isIsDark;
  309. },
  310. {
  311. deep: true,
  312. immediate: true,
  313. }
  314. );
  315. // 监听 vuex 中是否开启深色主题
  316. watch(
  317. () => store.state.themeConfig.themeConfig.isIsDark,
  318. (isIsDark) => {
  319. nextTick(() => {
  320. // if(!isIsDark) return
  321. state.charts.theme = isIsDark ? 'transparent' : '';
  322. state.charts.bgColor = isIsDark ? 'transparent' : '';
  323. state.charts.color = isIsDark ? '#dadada' : '#303133';
  324. setTimeout(() => {
  325. initLineChart('homeLineRef1');
  326. initLineChart('homeLineRef3');
  327. initLineChart('homeLineRef4');
  328. }, 1000);
  329. });
  330. },
  331. {
  332. deep: true,
  333. immediate: true,
  334. }
  335. );
  336. return {
  337. unitMap,
  338. tabName,
  339. homeLineRef1,
  340. homeLineRef3,
  341. homeLineRef4,
  342. homePieRef,
  343. homeBarRef,
  344. homeFourBarRef,
  345. // changePieType,
  346. getStatisticsLineChartData,
  347. ...toRefs(state),
  348. };
  349. },
  350. });
  351. </script>
  352. <style scoped lang="scss">
  353. $homeNavLengh: 8;
  354. .home-card-item-title {
  355. margin-left: 12px;
  356. margin-top: 3px;
  357. }
  358. .data-overview {
  359. overflow: hidden;
  360. // .home-card-one,
  361. .home-card-two,
  362. .home-card-three,
  363. .home-card-four {
  364. .home-card-item,
  365. .home-card-top {
  366. width: 100%;
  367. height: 100px;
  368. border-radius: 4px;
  369. transition: all ease 0.3s;
  370. padding: 10px;
  371. overflow: hidden;
  372. background: var(--el-color-white);
  373. color: var(--el-text-color-primary);
  374. border: 1px solid var(--next-border-color-light);
  375. &:hover {
  376. box-shadow: 0 2px 12px var(--next-color-dark-hover);
  377. transition: all ease 0.3s;
  378. }
  379. &-icon {
  380. width: 70px;
  381. height: 70px;
  382. border-radius: 100%;
  383. flex-shrink: 1;
  384. i {
  385. color: var(--el-text-color-placeholder);
  386. }
  387. }
  388. &-title {
  389. font-size: 15px;
  390. font-weight: bold;
  391. height: 30px;
  392. }
  393. }
  394. }
  395. .home-card-one {
  396. @for $i from 0 through 3 {
  397. .home-one-animation#{$i} {
  398. opacity: 0;
  399. animation-name: error-num;
  400. animation-duration: 0.5s;
  401. animation-fill-mode: forwards;
  402. animation-delay: calc($i/10) + s;
  403. }
  404. }
  405. }
  406. .home-card-one .home-card-item {
  407. width: 100%;
  408. border-radius: 4px;
  409. transition: all ease 0.3s;
  410. overflow: hidden;
  411. background: var(--el-color-white);
  412. color: var(--el-text-color-primary);
  413. border: 1px solid var(--next-border-color-light);
  414. &:hover {
  415. box-shadow: 0 2px 12px var(--next-color-dark-hover);
  416. transition: all ease 0.3s;
  417. }
  418. .item-header {
  419. display: flex;
  420. justify-content: center;
  421. align-content: center;
  422. color: #101010;
  423. padding: 10px 0;
  424. border-bottom: 1px solid var(--next-border-color-light);
  425. font-size: 20px;
  426. font-weight: bold;
  427. img {
  428. margin-right: 32px;
  429. width: 24px;
  430. height: 24px;
  431. margin-top: 3px;
  432. }
  433. }
  434. .item-content {
  435. padding: 16px;
  436. p {
  437. display: flex;
  438. justify-content: space-between;
  439. align-content: center;
  440. span:nth-child(1) {
  441. line-height: 30px;
  442. font-size: 14px;
  443. flex: 0 0 60px;
  444. }
  445. span:nth-child(2) {
  446. color: #101010;
  447. font-weight: bold;
  448. font-size: 22px;
  449. word-wrap: break-word;
  450. word-break: break-all;
  451. }
  452. }
  453. p:nth-child(2),
  454. p:nth-child(3) {
  455. margin-top: 5px;
  456. }
  457. }
  458. }
  459. .home-card-two,
  460. .home-card-three,
  461. .home-card-four {
  462. .home-card-item {
  463. height: 300px;
  464. }
  465. .home-card-top {
  466. height: 200px;
  467. .box-card {
  468. padding: 15px 20px 20px 10px;
  469. p {
  470. margin-bottom: 10px;
  471. }
  472. &-item {
  473. margin-bottom: 10px;
  474. }
  475. }
  476. }
  477. .home-card-item,
  478. .home-card-top {
  479. width: 100%;
  480. overflow: hidden;
  481. .home-monitor {
  482. height: 100%;
  483. .flex-warp-item {
  484. width: 25%;
  485. height: 111px;
  486. display: flex;
  487. .flex-warp-item-box {
  488. margin: auto;
  489. text-align: center;
  490. color: var(--el-text-color-primary);
  491. display: flex;
  492. border-radius: 5px;
  493. background: var(--next-bg-color);
  494. cursor: pointer;
  495. transition: all 0.3s ease;
  496. &:hover {
  497. background: var(--el-color-primary-light-9);
  498. transition: all 0.3s ease;
  499. }
  500. }
  501. @for $i from 0 through $homeNavLengh {
  502. .home-animation#{$i} {
  503. opacity: 0;
  504. animation-name: error-num;
  505. animation-duration: 0.5s;
  506. animation-fill-mode: forwards;
  507. animation-delay: calc($i/10) + s;
  508. }
  509. }
  510. }
  511. }
  512. }
  513. }
  514. .text-info {
  515. color: #23c6c8;
  516. }
  517. .text-danger {
  518. color: #ed5565;
  519. }
  520. .git-res {
  521. margin-top: 20px;
  522. }
  523. .git-res .el-link {
  524. margin-right: 30px;
  525. }
  526. ul,
  527. li {
  528. padding: 0;
  529. margin: 0;
  530. list-style: none;
  531. }
  532. .product {
  533. margin-top: 50px;
  534. h3 {
  535. margin-bottom: 15px;
  536. }
  537. }
  538. .product li {
  539. margin-bottom: 20px;
  540. float: left;
  541. width: 150px;
  542. }
  543. .box-card.xx {
  544. margin-top: 20px;
  545. }
  546. }
  547. .lable-group,
  548. .lable-group1 {
  549. // background-color: pink;
  550. display: flex;
  551. width: 100%;
  552. margin-top: 20px;
  553. border: 1px solid rgba(22, 132, 252, 1);
  554. > div {
  555. cursor: pointer;
  556. width: 33%;
  557. text-align: center;
  558. padding: 6px 0;
  559. color: rgba(22, 132, 252, 1);
  560. }
  561. div:nth-child(2) {
  562. border-left: 1px solid rgba(22, 132, 252, 1);
  563. border-right: 1px solid rgba(22, 132, 252, 1);
  564. }
  565. .active {
  566. background-color: rgba(22, 132, 252, 1);
  567. color: #fff;
  568. }
  569. }
  570. .lable-group1 > div {
  571. width: 50%;
  572. }
  573. </style>