DeviceAnalysis.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <template>
  2. <div class="device-analysis">
  3. <div style="height: 55px;display: flex;flex-direction: column;justify-content: flex-end;padding: 0 16px;">
  4. <el-select size="mini" v-model="collectEntityId" :disabled="!selectOptions || selectOptions.length <= 0" placeholder="请选择">
  5. <el-option
  6. v-for="item in selectOptions"
  7. :key="item.value"
  8. :label="item.label"
  9. :value="item.value">
  10. </el-option>
  11. </el-select>
  12. </div>
  13. <div v-if="selectOptions && selectOptions.length > 0" class="charts-outer">
  14. <div class="charts-inner">
  15. <jg-chart :_height="chartHeight" :option="optionToday"/>
  16. <div class="chart-right-text">
  17. <div>
  18. <div>运行占比</div>
  19. <div class="chart-right-text-rate">{{ durations.day.run }}%</div>
  20. </div>
  21. <div>
  22. <div>停机占比</div>
  23. <div class="chart-right-text-rate">{{ durations.day.stop }}%</div>
  24. </div>
  25. <div>
  26. <div>运行时长</div>
  27. <div v-if="durations.day.duration" class="chart-right-text-rate">{{ durations.day.duration }}</div>
  28. <div class="device-not-run-text" v-else>设备未运行</div>
  29. </div>
  30. </div>
  31. </div>
  32. <div class="charts-inner">
  33. <jg-chart :_height="chartHeight" :option="optionWeek"/>
  34. <div class="chart-right-text">
  35. <div>
  36. <div>运行占比</div>
  37. <div class="chart-right-text-rate">{{ durations.week.run }}%</div>
  38. </div>
  39. <div>
  40. <div>停机占比</div>
  41. <div class="chart-right-text-rate">{{ durations.week.stop }}%</div>
  42. </div>
  43. <div>
  44. <div>总运行时长</div>
  45. <div v-if="durations.week.duration" class="chart-right-text-rate">{{ durations.week.duration }}</div>
  46. <div class="device-not-run-text" v-else>设备未运行</div>
  47. </div>
  48. </div>
  49. </div>
  50. <div class="charts-inner">
  51. <jg-chart :_height="chartHeight" :option="optionMonth"/>
  52. <div class="chart-right-text">
  53. <div>
  54. <div>运行占比</div>
  55. <div class="chart-right-text-rate">{{ durations.month.run }}%</div>
  56. </div>
  57. <div>
  58. <div>停机占比</div>
  59. <div class="chart-right-text-rate">{{ durations.month.stop }}%</div>
  60. </div>
  61. <div>
  62. <div>总运行时长</div>
  63. <div v-if="durations.month.duration" class="chart-right-text-rate">{{ durations.month.duration }}</div>
  64. <div class="device-not-run-text" v-else>设备未运行</div>
  65. </div>
  66. </div>
  67. </div>
  68. <div class="charts-inner">
  69. <jg-chart :_height="chartHeight" :option="optionThreeMonth"/>
  70. <div class="chart-right-text">
  71. <div>
  72. <div>运行占比</div>
  73. <div class="chart-right-text-rate">{{ durations.threeMonth.run }}%</div>
  74. </div>
  75. <div>
  76. <div>停机占比</div>
  77. <div class="chart-right-text-rate">{{ durations.threeMonth.stop }}%</div>
  78. </div>
  79. <div>
  80. <div>总运行时长</div>
  81. <div v-if="durations.threeMonth.duration" class="chart-right-text-rate">{{ durations.threeMonth.duration }}</div>
  82. <div class="device-not-run-text" v-else>设备未运行</div>
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. <div v-else style="flex: 1" v-loading="true" element-loading-background="inherit"/>
  88. </div>
  89. </template>
  90. <script>
  91. import { findEntityByAcqId } from '@/api/CollectEntity'
  92. import JgChart from '@/components/JgChart'
  93. import { findDuration } from '@/api/DeviceRunRecord'
  94. import { mapState } from 'vuex'
  95. export default {
  96. name: 'DeviceAnalysis',
  97. components: { JgChart },
  98. props: {
  99. chartHeight: {
  100. type: String,
  101. default: '160px'
  102. },
  103. },
  104. data() {
  105. // 暗蓝色#4962FC,亮蓝色#4B7CF3,紫色#dd3ee5,绿色#12e78c,橙色#fe8104,青色#01C2F9,亮黄色#F4CB29,暗黄色 #FD9E06
  106. const colors = [
  107. '#4962FC', '#4B7CF3', '#dd3ee5', '#12e78c',
  108. '#fe8104', '#01C2F9', '#F4CB29', '#FD9E06',
  109. '#a171fa'
  110. ]
  111. return {
  112. selectOptions: [],
  113. collectEntityId: '',
  114. optionToday: {
  115. title: {
  116. text: '今日运行统计',
  117. left: 'left',
  118. top: 'top',
  119. textStyle: {
  120. fontSize: 16,
  121. color: '#FFF'
  122. },
  123. },
  124. series: [
  125. {
  126. type: 'pie',
  127. radius: ['40%', '70%'],
  128. center: ['60%', '60%'],
  129. avoidLabelOverlap: false,
  130. itemStyle: {
  131. borderRadius: 10,
  132. borderColor: '#fff',
  133. borderWidth: 2
  134. },
  135. label: {
  136. show: false,
  137. position: 'center'
  138. },
  139. emphasis: {
  140. label: {
  141. show: true,
  142. fontSize: 20,
  143. fontWeight: 'bold'
  144. }
  145. },
  146. labelLine: {
  147. show: false
  148. },
  149. data: [
  150. {
  151. value: 25,
  152. name: '停机时长',
  153. itemStyle: {
  154. color: '#999999'
  155. }
  156. },
  157. {
  158. value: 75,
  159. name: '运行时长',
  160. itemStyle: {
  161. color: colors[0],
  162. }
  163. },
  164. ]
  165. }
  166. ]
  167. },
  168. optionWeek: {
  169. title: {
  170. text: '本周运行统计',
  171. left: 'left',
  172. top: 'top',
  173. textStyle: {
  174. fontSize: 16,
  175. color: '#FFF'
  176. },
  177. },
  178. series: [
  179. {
  180. type: 'pie',
  181. radius: ['40%', '70%'],
  182. center: ['60%', '60%'],
  183. avoidLabelOverlap: false,
  184. itemStyle: {
  185. borderRadius: 10,
  186. borderColor: '#fff',
  187. borderWidth: 2
  188. },
  189. label: {
  190. show: false,
  191. position: 'center'
  192. },
  193. emphasis: {
  194. label: {
  195. show: true,
  196. fontSize: 20,
  197. fontWeight: 'bold'
  198. }
  199. },
  200. labelLine: {
  201. show: false
  202. },
  203. data: [
  204. {
  205. value: 25,
  206. name: '停机时长',
  207. itemStyle: {
  208. color: '#999999',
  209. fontSize: '16px'
  210. }
  211. },
  212. {
  213. value: 75,
  214. name: '运行时长',
  215. itemStyle: {
  216. color: colors[3],
  217. }
  218. },
  219. ]
  220. }
  221. ]
  222. },
  223. optionMonth: {
  224. title: {
  225. text: '本月运行统计',
  226. left: 'left',
  227. top: 'top',
  228. textStyle: {
  229. fontSize: 16,
  230. color: '#FFF'
  231. },
  232. },
  233. series: [
  234. {
  235. type: 'pie',
  236. radius: ['40%', '70%'],
  237. center: ['60%', '60%'],
  238. avoidLabelOverlap: false,
  239. itemStyle: {
  240. borderRadius: 10,
  241. borderColor: '#fff',
  242. borderWidth: 2
  243. },
  244. label: {
  245. show: false,
  246. position: 'center'
  247. },
  248. emphasis: {
  249. label: {
  250. show: true,
  251. fontSize: 20,
  252. fontWeight: 'bold'
  253. }
  254. },
  255. labelLine: {
  256. show: false
  257. },
  258. data: [
  259. {
  260. value: 25,
  261. name: '停机时长',
  262. itemStyle: {
  263. color: '#999999'
  264. }
  265. },
  266. {
  267. value: 75,
  268. name: '运行时长',
  269. itemStyle: {
  270. color: colors[8],
  271. }
  272. },
  273. ]
  274. }
  275. ]
  276. },
  277. optionThreeMonth: {
  278. title: {
  279. text: '三个月内运行统计',
  280. left: 'left',
  281. top: 'top',
  282. textStyle: {
  283. fontSize: 16,
  284. color: '#FFF'
  285. },
  286. },
  287. series: [
  288. {
  289. type: 'pie',
  290. radius: ['40%', '70%'],
  291. center: ['60%', '60%'],
  292. avoidLabelOverlap: false,
  293. itemStyle: {
  294. borderRadius: 10,
  295. borderColor: '#fff',
  296. borderWidth: 2
  297. },
  298. label: {
  299. show: false,
  300. position: 'center'
  301. },
  302. emphasis: {
  303. label: {
  304. show: true,
  305. fontSize: 20,
  306. fontWeight: 'bold'
  307. }
  308. },
  309. labelLine: {
  310. show: false
  311. },
  312. data: [
  313. {
  314. value: 25,
  315. name: '停机时长',
  316. itemStyle: {
  317. color: '#999999'
  318. }
  319. },
  320. {
  321. value: 76,
  322. name: '运行时长',
  323. itemStyle: {
  324. color: '#f18c27',
  325. }
  326. },
  327. ]
  328. }
  329. ]
  330. },
  331. durations: {
  332. day: {
  333. run: 0,
  334. stop: 0,
  335. duration: ''
  336. },
  337. week: {
  338. run: 0,
  339. stop: 0,
  340. duration: ''
  341. },
  342. month: {
  343. run: 0,
  344. stop: 0,
  345. duration: ''
  346. },
  347. threeMonth: {
  348. run: 0,
  349. stop: 0,
  350. duration: ''
  351. },
  352. },
  353. }
  354. },
  355. computed: {
  356. ...mapState({
  357. acquisitionStationId: state => state.company.acquisitionStationId,
  358. }),
  359. },
  360. watch: {
  361. collectEntityId: {
  362. handler() {
  363. this.fetchDuration()
  364. },
  365. },
  366. },
  367. methods: {
  368. getCollectEntity() {
  369. const params = {
  370. acquisitionStationId: this.acquisitionStationId
  371. }
  372. findEntityByAcqId(params).then(res => {
  373. if (res && res.code === '200') {
  374. const selectOptions = []
  375. for (const item of res.data) {
  376. if (item.isShow) {
  377. selectOptions.push({
  378. value: item.id,
  379. label: item.entityName
  380. })
  381. }
  382. }
  383. this.selectOptions = selectOptions
  384. this.collectEntityId = res.data[0].id
  385. } else {
  386. this.$message.error(res.message)
  387. }
  388. }).catch(reason => {
  389. console.error(reason)
  390. })
  391. },
  392. fetchDuration() {
  393. findDuration({ collectEntityId: this.collectEntityId }).then(res => {
  394. if (res && res.code === '200') {
  395. const today = this.optionToday.series
  396. today[0].data[0].value = res.data.day.stopDuration
  397. today[0].data[1].value = res.data.day.runDuration
  398. this.optionToday.series = today
  399. this.durations.day.run = Math.round(res.data.day.runDurationRate * 100)
  400. this.durations.day.stop = Math.round(res.data.day.stopDurationRate * 100)
  401. this.durations.day.duration = res.data.day.duration
  402. const week = this.optionWeek.series
  403. week[0].data[0].value = res.data.week.stopDuration
  404. week[0].data[1].value = res.data.week.runDuration
  405. this.optionWeek.series = week
  406. this.durations.week.run = Math.round(res.data.week.runDurationRate * 100)
  407. this.durations.week.stop = Math.round(res.data.week.stopDurationRate * 100)
  408. this.durations.week.duration = res.data.week.duration
  409. const month = this.optionMonth.series
  410. month[0].data[0].value = res.data.month.stopDuration
  411. month[0].data[1].value = res.data.month.runDuration
  412. this.optionMonth.series = month
  413. this.durations.month.run = Math.round(res.data.month.runDurationRate * 100)
  414. this.durations.month.stop = Math.round(res.data.month.stopDurationRate * 100)
  415. this.durations.month.duration = res.data.month.duration
  416. const threeMonth = this.optionThreeMonth.series
  417. threeMonth[0].data[0].value = res.data.threeMonth.stopDuration
  418. threeMonth[0].data[1].value = res.data.threeMonth.runDuration
  419. this.optionThreeMonth.series = threeMonth
  420. this.durations.threeMonth.run = Math.round(res.data.threeMonth.runDurationRate * 100)
  421. this.durations.threeMonth.stop = Math.round(res.data.threeMonth.stopDurationRate * 100)
  422. this.durations.threeMonth.duration = res.data.threeMonth.duration
  423. } else {
  424. this.$message.error(res.message)
  425. }
  426. })
  427. },
  428. },
  429. }
  430. </script>
  431. <style lang="less" scoped>
  432. .device-analysis {
  433. width: 100%;
  434. height: 100%;
  435. display: flex;
  436. flex-direction: column;
  437. .charts-outer {
  438. flex: 1;
  439. display: flex;
  440. padding: 0 16px;
  441. flex-direction: column;
  442. margin-top: 10px;
  443. .charts-inner {
  444. width: calc(100% - 16px);
  445. height: 100%;
  446. border-radius: 10px;
  447. box-shadow: inset 0.2rem 0.2rem 0.2rem #aaa7a7, inset -0.1rem -0.1rem 0.2rem #FFFFFF;
  448. padding: 8px;
  449. display: flex;
  450. margin: 35px 16px 0 0;
  451. }
  452. .charts-inner:first-child {
  453. margin-top: 0;
  454. }
  455. .chart-right-text {
  456. width: 100%;
  457. font-size: 16px;
  458. color: #FFF;
  459. display: flex;
  460. flex-direction: column;
  461. align-items: flex-start;
  462. justify-content: space-around;
  463. margin-left: 32px;
  464. .chart-right-text-rate {
  465. margin-top: 8px;
  466. font-size: 20px;
  467. font-weight: bolder;
  468. }
  469. .device-not-run-text {
  470. margin-top: 8px;
  471. font-size: 16px;
  472. color: #999999;
  473. }
  474. }
  475. }
  476. /deep/ .el-input--mini {
  477. font-size: 16px;
  478. }
  479. }
  480. </style>