right.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. <template>
  2. <div>
  3. <CusModule title="能耗统计">
  4. <div class="soc-stats-container">
  5. <div v-for="i in socList" :key="i.name" class="soc-stats-item" :style="{ backgroundImage: `url(${i.image})` }">
  6. <div class="soc-stats-info">
  7. <div class="mb-1">
  8. <span class="soc-stats-value">{{ i.value }}</span>
  9. <span class="unit">{{ i.unit }}</span>
  10. </div>
  11. <div class="soc-stats-label">
  12. {{ i.name }}
  13. </div>
  14. </div>
  15. </div>
  16. </div>
  17. </CusModule>
  18. <CusModule class="module-top" title="用能排名">
  19. <div class="soc-lst">
  20. <div v-for="(item, index) in ranking" :key="item.name" class="soc-itm">
  21. <div class="soc-num">
  22. {{ index + 1 }}
  23. </div>
  24. <div class="soc-dtl">
  25. <div class="txt-sm">
  26. {{ item.name }}
  27. </div>
  28. <CusProgress :value="item.value" :total="ranking.reduce((a, b) => a + b.value, 0)" :color="item.color"
  29. :labelWidth="95" unit="kW·h" showLabel></CusProgress>
  30. </div>
  31. </div>
  32. </div>
  33. </CusModule>
  34. <CusModule class="module-top" title="用能趋势预测">
  35. <BaseChart height="350px" width="100%" :option="lineOptions"/>
  36. </CusModule>
  37. </div>
  38. </template>
  39. <script>
  40. import CusModule from '../components/CusModule.vue';
  41. import CusProgress from '../components/CusProgress.vue';
  42. import BaseChart from '@/components/BaseChart/index.vue'
  43. import * as echarts from 'echarts'
  44. import {dateFormat, numToStr} from '@/utils'
  45. import {mapState} from 'vuex';
  46. import {qryElecMeterByDate, qryWaterMeterByDate} from "@/api/device/elecMeterH";
  47. import {DateTool} from "@/utils/DateTool";
  48. export default {
  49. name: 'SocRight',
  50. data() {
  51. return {
  52. socList: [
  53. {
  54. name: "电",
  55. image: require("@/assets/images/soc/item1.png"),
  56. unit: "kW·h",
  57. },
  58. // {
  59. // name: "燃气",
  60. // image: require("@/assets/images/soc/item2.png"),
  61. // value: 7945,
  62. // unit: "kg",
  63. // },
  64. {
  65. name: "水",
  66. image: require("@/assets/images/soc/item3.png"),
  67. unit: "吨",
  68. },
  69. ],
  70. ranking: [
  71. {
  72. name: "公共设施",
  73. color: "#14c5f2",
  74. value: 500,
  75. },
  76. {
  77. name: "空调",
  78. color: "#14c5f2",
  79. value: 400,
  80. },
  81. {
  82. name: "照明",
  83. color: "#14c5f2",
  84. value: 300,
  85. },
  86. {
  87. name: "电梯",
  88. color: "#14c5f2",
  89. value: 100,
  90. },
  91. {
  92. name: "其他",
  93. color: "#14c5f2",
  94. value: 100,
  95. },
  96. ],
  97. lineData: []
  98. }
  99. },
  100. components: {
  101. CusModule,
  102. CusProgress,
  103. BaseChart,
  104. },
  105. computed: {
  106. ...mapState('userState', ['areaType']),
  107. lineOptions() {
  108. return {
  109. grid: {
  110. top: "10%",
  111. bottom: "10%",//也可设置left和right设置距离来控制图表的大小
  112. contain: true
  113. },
  114. tooltip: {
  115. trigger: "axis",
  116. axisPointer: {
  117. type: "shadow",
  118. label: {
  119. show: true
  120. }
  121. }
  122. },
  123. legend: {
  124. data: ["用电量", "当日最高负荷"],
  125. textStyle: {
  126. color: "#ffffff"
  127. }
  128. },
  129. xAxis: {
  130. data: this.lineData.map(item => item.xData),
  131. axisLine: {
  132. show: true, //隐藏X轴轴线
  133. },
  134. axisTick: {
  135. show: true //隐藏X轴刻度
  136. },
  137. axisLabel: {
  138. show: true,
  139. },
  140. },
  141. yAxis: [{
  142. type: "value",
  143. name: "kW·h",
  144. splitLine: {
  145. show: true,
  146. lineStyle: {
  147. color: '#334E5E'
  148. }
  149. },
  150. },
  151. {
  152. type: "value",
  153. name: "kW",
  154. position: "right",
  155. splitLine: {
  156. show: false
  157. },
  158. }
  159. ],
  160. series: [
  161. {
  162. name: "用电量",
  163. type: "bar",
  164. barWidth: 15,
  165. itemStyle: {
  166. normal: {
  167. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  168. offset: 0,
  169. color: "#21C3E8"
  170. },
  171. {
  172. offset: 0.7,
  173. color: "#1484A1"
  174. },
  175. {
  176. offset: 1,
  177. color: "#0B2B38"
  178. }
  179. ])
  180. }
  181. },
  182. data: this.lineData.map(item => item.yData1)
  183. },
  184. {
  185. name: "当日最高负荷",
  186. type: "line",
  187. yAxisIndex: 1, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
  188. smooth: true, //平滑曲线显示
  189. itemStyle: {
  190. color: "#F5D6AD",
  191. borderColor: "#fff",
  192. borderWidth: 3
  193. },
  194. lineStyle: {
  195. color: "#F5D6AD"
  196. },
  197. areaStyle: {
  198. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  199. offset: 0,
  200. color: "#A18C74"
  201. },
  202. {
  203. offset: 1,
  204. color: "transparent"
  205. }
  206. ])
  207. },
  208. markLine: {
  209. symbol: 'none',
  210. silent: true,
  211. lineStyle: {normal: {type: 'dashed'}},
  212. label: {position: 'start'},
  213. data: [
  214. {
  215. yAxis: 190,
  216. lineStyle: {width: 1.656, color: '#ff6367'},
  217. label: {show: false}
  218. },
  219. ]
  220. },
  221. markPoint: {
  222. silent: true,
  223. data: [
  224. {
  225. yAxis: 190,
  226. x: '100%',
  227. symbolSize: 0.1,
  228. label: {
  229. textStyle: {color: '#F59A23'},
  230. fontSize: 12,
  231. position: 'left',
  232. formatter: '历史最高负荷'
  233. }
  234. },
  235. ]
  236. },
  237. data: this.lineData.map(item => item.yData2)
  238. },
  239. ]
  240. }
  241. }
  242. },
  243. watch: {
  244. areaType() {
  245. this.getSocData()
  246. }
  247. },
  248. mounted() {
  249. this.getSocData()
  250. },
  251. methods: {
  252. getDatesOfLastTenDays() {
  253. var dates = [];
  254. var today = new Date();
  255. for (var i = 1; i < 11; i++) {
  256. var pastDate = new Date(today);
  257. pastDate.setDate(today.getDate() + i); // 减去i天
  258. var formattedDate = dateFormat(pastDate, 'MM-dd');
  259. dates.push(formattedDate);
  260. }
  261. return dates.map(item => ({
  262. xData: item,
  263. yData1: parseFloat(((Math.random() * 100 + 200)).toFixed(1)),
  264. yData2: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
  265. }));
  266. },
  267. getSocData() {
  268. this.lineData = this.getDatesOfLastTenDays()
  269. this.getMeterElecWater()
  270. this.ranking = this.ranking.map((item, index) => ({
  271. ...item,
  272. value: Math.floor(Math.random() * 100 + (index + 1) * 100)
  273. })).reverse();
  274. },
  275. async getMeterElecWater() {
  276. const {data: elecMeter} = await qryElecMeterByDate(DateTool.now(), this.areaType)
  277. const {data: waterMeter} = await qryWaterMeterByDate(DateTool.now(), this.areaType)
  278. const [elec, water] = this.socList
  279. elec.value = numToStr(elecMeter.elecQuantity)
  280. water.value = numToStr(waterMeter.waterQuantity)
  281. this.socList = [elec, water]
  282. },
  283. }
  284. }
  285. </script>
  286. <style lang='scss' scoped>
  287. @import url("../index.scss");
  288. .soc-stats-container {
  289. display: flex;
  290. justify-content: space-between;
  291. margin-top: 20px;
  292. padding: 0 40px;
  293. .soc-stats-item {
  294. position: relative;
  295. width: 120px;
  296. height: 138px;
  297. background-size: cover;
  298. .soc-stats-info {
  299. position: absolute;
  300. bottom: -2px;
  301. width: 100%;
  302. text-align: center;
  303. .soc-stats-value {
  304. font-size: 18px;
  305. font-weight: bold;
  306. color: #06E3F9;
  307. }
  308. .soc-stats-label {
  309. color: #B3E3E8;
  310. font-size: 14px;
  311. margin-top: 2px;
  312. }
  313. }
  314. }
  315. }
  316. .soc-lst {
  317. height: 100%;
  318. padding-top: 6px;
  319. padding-bottom: 6px;
  320. display: flex;
  321. flex-direction: column;
  322. align-items: center;
  323. overflow-y: auto;
  324. .soc-itm {
  325. width: 332px;
  326. height: 45px;
  327. background-image: url('~@/assets/images/soc/r2-list.png');
  328. background-repeat: no-repeat;
  329. display: flex;
  330. align-items: center;
  331. .soc-num {
  332. width: 53px;
  333. margin-right: 16px;
  334. display: flex;
  335. align-items: center;
  336. justify-content: center;
  337. }
  338. .soc-dtl {
  339. padding-right: 2px;
  340. width: 100%;
  341. .txt-sm {
  342. color: #B3E3E8;
  343. font-size: 12px;
  344. margin-bottom: 5px;
  345. }
  346. }
  347. }
  348. }
  349. .seamless-header {
  350. margin-top: 20px;
  351. display: flex;
  352. align-items: center;
  353. justify-content: space-between;
  354. padding: 5px 10px;
  355. color: #7DBAFF;
  356. background: #1B4A64;
  357. font-size: 16px;
  358. > div:first-of-type,
  359. > div:last-of-type {
  360. flex-basis: 35%;
  361. }
  362. > div {
  363. text-align: center;
  364. }
  365. }
  366. .seamless-warp {
  367. overflow: hidden;
  368. height: 200px;
  369. .seamless-item {
  370. display: flex;
  371. align-items: center;
  372. justify-content: space-between;
  373. padding: 5px 0;
  374. &:nth-child(odd) {
  375. background: #000;
  376. }
  377. > div:first-of-type,
  378. > div:last-of-type {
  379. flex-basis: 38%;
  380. }
  381. > div {
  382. text-align: center;
  383. font-size: 13px;
  384. }
  385. }
  386. }
  387. </style>