InternetDryingBox.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. <template>
  2. <view class="InternetDryingBox">
  3. <view class="mainBox-image">
  4. <view class="image-title">实时温度</view>
  5. <view class="image-list">
  6. <view class="list-swiper">
  7. <l-echart ref="chart"></l-echart>
  8. </view>
  9. <view class="list-swiper">
  10. <l-echart ref="chart1"></l-echart>
  11. </view>
  12. <view class="list-swiper">
  13. <l-echart ref="chart2"></l-echart>
  14. </view>
  15. <view class="list-swiper">
  16. <l-echart ref="chart3"></l-echart>
  17. </view>
  18. </view>
  19. </view>
  20. <view>
  21. <uni-table border stripe emptyText="暂无更多数据">
  22. <!-- 表头行 -->
  23. <uni-tr>
  24. <uni-th align="center" width="180rpx"></uni-th>
  25. <uni-th align="center">温度1</uni-th>
  26. <uni-th align="center">温度2</uni-th>
  27. <uni-th align="center">温度3</uni-th>
  28. <uni-th align="center">温度4</uni-th>
  29. </uni-tr>
  30. <!-- 表格数据行 -->
  31. <template v-if="tableData.length">
  32. <uni-tr>
  33. <uni-td>当日峰值</uni-td>
  34. <uni-td>{{ tableData[0].maxValue }}</uni-td>
  35. <uni-td>{{ tableData[1].maxValue }}</uni-td>
  36. <uni-td>{{ tableData[2].maxValue }}</uni-td>
  37. <uni-td>{{ tableData[3].maxValue }}</uni-td>
  38. </uni-tr>
  39. <uni-tr>
  40. <uni-td>当日谷值</uni-td>
  41. <uni-td>{{ tableData[0].minValue }}</uni-td>
  42. <uni-td>{{ tableData[1].minValue }}</uni-td>
  43. <uni-td>{{ tableData[2].minValue }}</uni-td>
  44. <uni-td>{{ tableData[3].minValue }}</uni-td>
  45. </uni-tr>
  46. <uni-tr>
  47. <uni-td>当日均值</uni-td>
  48. <uni-td>{{ tableData[0].avgValue }}</uni-td>
  49. <uni-td>{{ tableData[1].avgValue }}</uni-td>
  50. <uni-td>{{ tableData[2].avgValue }}</uni-td>
  51. <uni-td>{{ tableData[3].avgValue }}</uni-td>
  52. </uni-tr>
  53. </template>
  54. </uni-table>
  55. </view>
  56. </view>
  57. </template>
  58. <script>
  59. import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
  60. import { get, postJ } from '@/utils/api.js'
  61. import { debounce } from 'lodash'
  62. import mqtt from './mqtt'
  63. export default {
  64. mixins: [mqtt],
  65. data () {
  66. return {
  67. opts: {},
  68. chartData: {},
  69. tableData: [],
  70. propertyList: [
  71. {
  72. name: '温度1',
  73. property: 'temp1'
  74. },
  75. {
  76. name: '温度2',
  77. property: 'temp2'
  78. },
  79. {
  80. name: '温度3',
  81. property: 'temp3'
  82. },
  83. {
  84. name: '温度4',
  85. property: 'temp4'
  86. }
  87. ],
  88. // mqtt 订阅类别
  89. topIc_type: 'DRYING_OVEN_TOPIC'
  90. }
  91. },
  92. props: ['realData', 'info'],
  93. computed: {
  94. // mqtt topic
  95. TOPIC () {
  96. if (this.info.iotId) {
  97. return {
  98. topic: `/${this.topIc_type}/${this.info.iotId}`,
  99. qos: 0
  100. }
  101. } else {
  102. return null
  103. }
  104. }
  105. },
  106. created () {
  107. this.getTableData()
  108. if (this.TOPIC) {
  109. this.mqttInit()
  110. }
  111. },
  112. mounted () {
  113. this.initGauge()
  114. },
  115. methods: {
  116. initGauge () {
  117. let option = this.getGaugeOption(
  118. this.realData.temp1 ? this.realData.temp1.value : 0,
  119. '温度1'
  120. )
  121. this.$refs.chart.init(echarts, chart => {
  122. chart.setOption(option)
  123. })
  124. let option1 = this.getGaugeOption(
  125. this.realData.temp2 ? this.realData.temp2.value : 0,
  126. '温度2'
  127. )
  128. this.$refs.chart1.init(echarts, chart => {
  129. chart.setOption(option1)
  130. })
  131. let option2 = this.getGaugeOption(
  132. this.realData.temp3 ? this.realData.temp3.value : 0,
  133. '温度3'
  134. )
  135. this.$refs.chart2.init(echarts, chart => {
  136. chart.setOption(option2)
  137. })
  138. let option3 = this.getGaugeOption(
  139. this.realData.temp4 ? this.realData.temp4.value : 0,
  140. '温度4'
  141. )
  142. this.$refs.chart3.init(echarts, chart => {
  143. chart.setOption(option3)
  144. })
  145. },
  146. async getTableData () {
  147. function fnNum (num) {
  148. return num < 10 ? '0' + num : num
  149. }
  150. let startTime
  151. let endTime
  152. let ndate = new Date()
  153. let year = ndate.getFullYear()
  154. let month = ndate.getMonth() + 1
  155. let day = ndate.getDate()
  156. let _date = `${year}-${fnNum(month)}-${fnNum(day)}`
  157. startTime = _date + ' 00:00:00'
  158. endTime = _date + ' 23:59:59'
  159. const resList = await Promise.all(
  160. this.propertyList.map(i =>
  161. postJ(
  162. this.apiUrl +
  163. `/asset/getEquHistory?equId=${this.info.id}&startTime=${startTime}&endTime=${endTime}&timeType=3&property=${i.property}`
  164. )
  165. )
  166. )
  167. this.tableData = resList.map(i => {
  168. if (i?.success) {
  169. return i.data || {}
  170. }
  171. return {}
  172. })
  173. },
  174. // mqtt处理数据
  175. initMqttData (items) {
  176. console.log('mqtt处理数据', items)
  177. for (const [key, obj] of Object.entries(items)) {
  178. const realData = this.realData
  179. realData[key].value = obj.value
  180. realData[key].time = obj.time
  181. this.$emit('update:realData', realData)
  182. }
  183. let initGauge = debounce(this.initGauge, 1000)
  184. initGauge()
  185. },
  186. //指针和起点覆盖
  187. getGaugeSeriesCover () {
  188. return {
  189. detail: {
  190. show: false
  191. },
  192. startAngle: 180,
  193. endAngle: -0,
  194. splitNumber: 2,
  195. radius: '84%',
  196. type: 'gauge',
  197. title: {
  198. show: false
  199. },
  200. axisLabel: {
  201. show: false
  202. },
  203. splitLine: {
  204. show: false
  205. },
  206. axisTick: {
  207. show: false
  208. },
  209. axisLine: {
  210. show: false
  211. },
  212. progress: {
  213. show: false
  214. },
  215. itemStyle: {
  216. color: '#7a71ff',
  217. shadowColor: 'rgba(0,138,255,0.45)',
  218. shadowBlur: 10,
  219. shadowOffsetX: 2,
  220. shadowOffsetY: 2,
  221. borderCap: 'round'
  222. },
  223. anchor: {
  224. show: true,
  225. showAbove: false,
  226. offsetCenter: ['-98.5%', -1],
  227. size: 10,
  228. icon: 'circle',
  229. itemStyle: {
  230. color: '#98a4f2',
  231. borderColor: '#fff',
  232. backgroundColor: '#98a4f2',
  233. borderWidth: 5
  234. }
  235. },
  236. pointer: {
  237. show: true,
  238. icon: 'image://data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IuWbvuWxgl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMjAwIDIwMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjAwIDIwMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiNGRkZGRkY7fQoJLnN0MXtmaWxsOiM0MDYzRDE7fQo8L3N0eWxlPgo8cmVjdCB4PSI2Ny43IiB5PSI3NC43IiBjbGFzcz0ic3QwIiB3aWR0aD0iNjYuOSIgaGVpZ2h0PSI2OC43Ii8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0xNzUsMTA4LjNjMCw0MS40LTMzLjYsNzUtNzUsNzVzLTc1LTMzLjYtNzUtNzVzNjQuNi05MS43LDc1LTkxLjdTMTc1LDY2LjksMTc1LDEwOC4zeiBNNzcuMSwxMDguMwoJYzAsMTIuNywxMC4zLDIyLjksMjIuOSwyMi45czIyLjktMTAuMywyMi45LTIyLjlTMTEyLjcsODUuNCwxMDAsODUuNFM3Ny4xLDk1LjcsNzcuMSwxMDguM3oiLz4KPC9zdmc+Cg==',
  239. length: '18%',
  240. width: '16%',
  241. keepAspect: true,
  242. offsetCenter: [0, '-90%']
  243. }
  244. }
  245. },
  246. getGaugeOption (data, chartName) {
  247. const max = this.getMax(data || 0, 100)
  248. const min = 0
  249. return {
  250. tooltip: {
  251. show: false
  252. },
  253. series: [
  254. {
  255. zlevel: 1,
  256. min,
  257. max,
  258. startAngle: 180,
  259. endAngle: -0,
  260. splitNumber: 2,
  261. radius: '55%',
  262. type: 'gauge',
  263. detail: {
  264. width: '60%',
  265. lineHeight: 40,
  266. height: 40,
  267. fontSize: 20,
  268. borderRadius: 8,
  269. offsetCenter: [0, '-20%'],
  270. valueAnimation: true,
  271. formatter: function (value) {
  272. return `${value}℃`
  273. }
  274. },
  275. title: {
  276. show: true,
  277. offsetCenter: [0, '14%'],
  278. color: '#9e9e9e',
  279. fontSize: 14
  280. },
  281. axisLabel: {
  282. rotate: 360,
  283. distance: -10,
  284. color: '#666',
  285. fontSize: 16
  286. },
  287. splitLine: {
  288. show: true,
  289. length: 8,
  290. distance: -20,
  291. lineStyle: {
  292. width: 1,
  293. color: '#666'
  294. }
  295. },
  296. axisTick: {
  297. show: true,
  298. splitNumber: 10,
  299. distance: -15,
  300. length: 4,
  301. lineStyle: {
  302. height: 2,
  303. color: '#666'
  304. }
  305. },
  306. axisLine: {
  307. show: false
  308. },
  309. progress: {
  310. show: true,
  311. roundCap: true,
  312. width: 2,
  313. showAbove: false,
  314. itemStyle: {
  315. color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
  316. {
  317. offset: 0,
  318. color: '#15b4ff'
  319. },
  320. {
  321. offset: 1,
  322. color: '#716dff'
  323. }
  324. ]),
  325. shadowColor: 'rgba(0,138,255,0.45)',
  326. shadowBlur: 10,
  327. shadowOffsetX: 2,
  328. shadowOffsetY: 2
  329. }
  330. },
  331. itemStyle: {
  332. color: '#7a71ff',
  333. shadowColor: 'rgba(0,138,255,0.45)',
  334. shadowBlur: 10,
  335. shadowOffsetX: 2,
  336. shadowOffsetY: 2,
  337. borderCap: 'round'
  338. },
  339. anchor: {
  340. show: true,
  341. showAbove: false,
  342. offsetCenter: ['-98%', '-1.2%'],
  343. size: 8,
  344. icon: 'circle',
  345. itemStyle: {
  346. color: '#98a4f2',
  347. borderColor: '#fff',
  348. backgroundColor: '#98a4f2',
  349. borderWidth: 5
  350. }
  351. },
  352. pointer: {
  353. show: true,
  354. icon: 'pin',
  355. // icon: 'image://data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IuWbvuWxgl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMjAwIDIwMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjAwIDIwMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiNGRkZGRkY7fQoJLnN0MXtmaWxsOiM0MDYzRDE7fQo8L3N0eWxlPgo8cmVjdCB4PSI2Ny43IiB5PSI3NC43IiBjbGFzcz0ic3QwIiB3aWR0aD0iNjYuOSIgaGVpZ2h0PSI2OC43Ii8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0xNzUsMTA4LjNjMCw0MS40LTMzLjYsNzUtNzUsNzVzLTc1LTMzLjYtNzUtNzVzNjQuNi05MS43LDc1LTkxLjdTMTc1LDY2LjksMTc1LDEwOC4zeiBNNzcuMSwxMDguMwoJYzAsMTIuNywxMC4zLDIyLjksMjIuOSwyMi45czIyLjktMTAuMywyMi45LTIyLjlTMTEyLjcsODUuNCwxMDAsODUuNFM3Ny4xLDk1LjcsNzcuMSwxMDguM3oiLz4KPC9zdmc+Cg==',
  356. length: '26%',
  357. width: '23%',
  358. keepAspect: true,
  359. offsetCenter: [0, '-95%']
  360. },
  361. center: ['48%', '54%'],
  362. name: 'Temperature',
  363. backgroundColor: '#000',
  364. data: [
  365. {
  366. value: data,
  367. name: chartName
  368. }
  369. ]
  370. }
  371. // {
  372. // min,
  373. // max,
  374. // zlevel: 2,
  375. // ...this.getGaugeSeriesCover(),
  376. // // center: ['48%', '77%'],
  377. // center: ['49%', '62%'],
  378. // name: 'Temperature',
  379. // backgroundColor: '#000',
  380. // data: [
  381. // {
  382. // value: data,
  383. // name: chartName
  384. // }
  385. // ]
  386. // }
  387. ]
  388. }
  389. },
  390. getMax (data, def = 100) {
  391. let half = def / 2
  392. if (data <= def) {
  393. return def
  394. }
  395. const n = data % half
  396. const m = Math.floor(data / half)
  397. return n === 0 ? m * half : (m + 1) * half
  398. }
  399. }
  400. }
  401. </script>
  402. <style lang="scss" scoped>
  403. .InternetDryingBox /deep/.uni-table {
  404. min-width: 100vw !important;
  405. .uni-table-td,
  406. .uni-table-th {
  407. padding: 20rpx 10rpx !important;
  408. text-align: center !important;
  409. }
  410. }
  411. .mainBox-image {
  412. width: 100%;
  413. .image-title {
  414. width: 98%;
  415. margin: 16rpx auto 0;
  416. font-size: 28rpx;
  417. font-weight: bold;
  418. color: #000;
  419. }
  420. .image-list {
  421. width: 100vw;
  422. display: flex;
  423. align-items: center;
  424. justify-content: space-between;
  425. flex-wrap: wrap;
  426. .list-swiper {
  427. width: 50%;
  428. height: 400rpx;
  429. background: url('~@/static/charts/dryingBox-bg.jpg') no-repeat 50% 50%;
  430. // background-image: url('~@/assets/img/charts/dryingBox-bg.jpg');
  431. background-size: 77% auto;
  432. }
  433. }
  434. }
  435. </style>