mls.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. <template>
  2. <view>
  3. <!-- <view class="status_bar"></view> -->
  4. <view class="" style="position: relative">
  5. <!-- <view style="position: fixed; z-index: 100; width: 100%">
  6. <uni-nav-bar @clickLeft="clickLeft" left-icon="back" left-text="返回" title="设备详情"></uni-nav-bar>
  7. </view> -->
  8. <view class="info">
  9. <view class="info_item">
  10. <image
  11. :src="$imageURL+'/bigdata_app/image/cb/onBg.png'"
  12. mode=""
  13. class="bgi"
  14. ></image>
  15. <p style="font-size: 32rpx" @click="copy(eqinfo.device_id)">
  16. 设备 ID:{{ eqinfo.device_id }}
  17. <image
  18. :src="$imageURL+'/bigdata_app/image/environment/fuzhi.png'"
  19. mode=""
  20. class="tishi"
  21. ></image>
  22. </p>
  23. <p>设备名称:{{ eqinfo.device_name || '无' }}</p>
  24. <p>
  25. 最近上报时间:<span v-if="eqinfo.uptime">{{
  26. eqinfo.uptime == 0 ? '无' : eqinfo.uptime | timeFormat()
  27. }}</span
  28. ><span v-else>{{
  29. eqinfo.uptime == 0 ? '无' : eqinfo.uptime | timeFormat()
  30. }}</span>
  31. </p>
  32. <p>地址:{{ eqinfo.location || '暂无地址' }}</p>
  33. </view>
  34. </view>
  35. <view class="control">
  36. <view class="control_item" v-if="kongtf" @click="control">
  37. <image
  38. :src="
  39. $imageURL+ '/bigdata_app' +
  40. '/image/environment/forecastResult.png'
  41. "
  42. mode=""
  43. ></image>
  44. <p>防控决策</p>
  45. </view>
  46. </view>
  47. <view class="his_box" v-if="datatf">
  48. <view class="selecttimes" @click="tiemshow = !tiemshow">
  49. <view class="timesbox">
  50. <image
  51. :src="$imageURL+'/bigdata_app/image/prevention/1acfe2751c01d3786cdc49b83d7e505.png'"
  52. mode=""
  53. ></image>
  54. <p>{{ timetab(begintime) }}</p>
  55. <p class="or">~</p>
  56. <p>{{ timetab(end) }}</p>
  57. <u-icon
  58. name="rili"
  59. custom-prefix="custom-icon"
  60. class="icon"
  61. ></u-icon>
  62. </view>
  63. <u-calendar
  64. v-model="tiemshow"
  65. mode="range"
  66. @change="tiemchange"
  67. ></u-calendar>
  68. </view>
  69. <view class="shuju_one">
  70. <view class="canvastishi" v-if="!canvastishiTF && !dataloadingtf">
  71. 暂无数据
  72. </view>
  73. <view class="canvastishi" v-if="dataloadingtf">
  74. <p class="dataloading">加载中</p>
  75. </view>
  76. <canvas
  77. v-show="!tiemshow"
  78. canvas-id="canvasColumnA"
  79. id="canvasColumnA"
  80. class="charts"
  81. @touchstart="touchLineA($event)"
  82. @touchmove="moveLineA($event)"
  83. @touchend="touchEndLineA($event)"
  84. disable-scroll="true"
  85. :style="{
  86. width: cWidth * pixelRatio + 'px',
  87. height: cHeight * pixelRatio + 'px',
  88. transform: 'scale(' + 1 / pixelRatio + ')',
  89. 'margin-left': (-cWidth * (pixelRatio - 1)) / 2 + 'px',
  90. 'margin-top': (-cHeight * (pixelRatio - 1)) / 2 + 'px',
  91. }"
  92. ></canvas>
  93. <canvas
  94. v-show="!tiemshow"
  95. canvas-id="canvasColumnB"
  96. id="canvasColumnB"
  97. class="charts"
  98. @touchstart="touchLineB($event)"
  99. @touchmove="moveLineB($event)"
  100. @touchend="touchEndLineB($event)"
  101. disable-scroll="true"
  102. :style="{
  103. width: cWidth * pixelRatio + 'px',
  104. height: cHeight * pixelRatio + 'px',
  105. transform: 'scale(' + 1 / pixelRatio + ')',
  106. 'margin-left': (-cWidth * (pixelRatio - 1)) / 2 + 'px',
  107. 'margin-top': (-cHeight * (pixelRatio - 1)) / 2 + 'px',
  108. }"
  109. ></canvas>
  110. </view>
  111. <view class="condition">
  112. <scroll-view scroll-top="0" scroll-x="true" class="scroll-X">
  113. <table class="table">
  114. <tr class="tr">
  115. <th class="th" v-for="(value, key) in param" :key="'a' + key">
  116. {{ value }}
  117. </th>
  118. </tr>
  119. <tr
  120. class="tr"
  121. v-for="(items, indexs) in historylistdata"
  122. :key="'b' + indexs"
  123. v-if="!forbidden"
  124. >
  125. <td class="td" v-for="(value, key) in param">
  126. {{ items[key] }}
  127. </td>
  128. </tr>
  129. <tr class="tr" v-if="forbidden">
  130. <td class="td" v-for="item in 13">暂无数据</td>
  131. </tr>
  132. </table>
  133. </scroll-view>
  134. <view class="pagenumber">
  135. <button @click="prev">上一页</button>
  136. <view class="pagenumber_page"> 第 {{ page }} 页 </view>
  137. <view class="pagenumber_page"> 共 {{ pagesum }} 页 </view>
  138. <button @click="next">下一页</button>
  139. </view>
  140. </view>
  141. </view>
  142. </view>
  143. </view>
  144. </template>
  145. <script>
  146. import uCharts from '../../../components/js_sdk/u-charts/u-charts/u-charts.js';
  147. var canvaColumnA = null;
  148. var canvaColumnB = null;
  149. export default {
  150. data() {
  151. return {
  152. basetype: '',
  153. kongtf: false,
  154. datatf: false,
  155. eqinfo: {},
  156. city: '河南省',
  157. tiemshow: false, //时间筛选弹框
  158. begintime: '', //开始时间
  159. end: '', //结束时间
  160. dataloadingtf: true,
  161. canvastishiTF: false,
  162. device_id: '', //设备ID
  163. forbidden: false,
  164. historylistdata: [], //历史数据
  165. pagesum: 1,
  166. page: 1,
  167. cWidth: '',
  168. cHeight: '',
  169. pixelRatio: 1,
  170. param: {},
  171. color: [
  172. '#ff7b30',
  173. '#f93948',
  174. '#fb2ea4',
  175. '#bc59db',
  176. '#7457ec',
  177. '#307dfd',
  178. '#31bfff',
  179. '#46e9b1',
  180. '#19cd48',
  181. '#b2e409',
  182. '#f0f254',
  183. '#fed000',
  184. '#f06f14',
  185. '#a74040',
  186. '#90bb71',
  187. '#a07635',
  188. '#6502bd',
  189. '#048bbb',
  190. '#9ebb01',
  191. '#cc9202',
  192. '#ff8fa0',
  193. '#a3d55f',
  194. '#d9bedd',
  195. '#00a6b6',
  196. '#236093',
  197. '#009fff',
  198. '#ddc0a6',
  199. '#c4a6dd',
  200. '#dda6a6',
  201. '#779e33',
  202. '#a6ddb0',
  203. ],
  204. };
  205. },
  206. methods: {
  207. copy(item) {
  208. uni.setClipboardData({
  209. data: item,
  210. success: function () {
  211. console.log('success');
  212. },
  213. });
  214. },
  215. control() {
  216. //设备控制
  217. uni.navigateTo({
  218. url: './forecastResult?id=' + this.eqinfo.device_id,
  219. });
  220. },
  221. tiemchange(e) {
  222. console.log(e);
  223. //切换时间
  224. // this.begintime = parseInt(+new Date(e.startDate) / 1000);
  225. this.begintime = parseInt(+new Date(`${e.startDate} 00:00:00`) / 1000);
  226. this.end = parseInt(+new Date(`${e.endDate} 00:00:00`) / 1000);
  227. this.histprydatas();
  228. this.getChartLine();
  229. },
  230. timetab(e) {
  231. //时间转换
  232. e = new Date(e * 1000);
  233. var year = e.getFullYear();
  234. var month =
  235. e.getMonth() + 1 < 10 ? '0' + (e.getMonth() + 1) : e.getMonth() + 1;
  236. var day = e.getDate() < 10 ? '0' + e.getDate() : e.getDate();
  237. var time = year + '/' + month + '/' + day;
  238. return time;
  239. },
  240. // 表格数据
  241. async histprydatas() {
  242. //表格历史数据
  243. const res = await this.$myRequest({
  244. url: '/api/api_gateway?method=wheat.potato.potato_data_list',
  245. data: {
  246. device_id: this.eqinfo.device_id,
  247. page: this.page,
  248. begin: this.begintime,
  249. end: this.end,
  250. },
  251. });
  252. console.log(res);
  253. this.param = res.ele;
  254. this.pagesum = Math.ceil(res.nums / 10) || 1;
  255. if (this.pagesum > 0) {
  256. var dat = res.sta;
  257. this.historylistdata = [];
  258. for (var i = 0; i < dat.length; i++) {
  259. var item = eval('(' + dat[i] + ')');
  260. var obj = {};
  261. for (var i1 in item) {
  262. // if (i1 == "uploadTime") {
  263. // obj[i1] = this.formatTime(item[i1] * 1000);
  264. // } else {
  265. obj[i1] = item[i1];
  266. // }
  267. }
  268. this.historylistdata.push(obj);
  269. }
  270. } else {
  271. this.historylistdata = [];
  272. }
  273. },
  274. //获取折线图数据
  275. async getChartLine() {
  276. const res = await this.$myRequest({
  277. method: 'POST',
  278. url: '/api/api_gateway?method=wheat.potato.potato_data',
  279. data: {
  280. device_id: this.eqinfo.device_id,
  281. begin: this.begintime,
  282. end: this.end,
  283. },
  284. });
  285. this.dataloadingtf = false;
  286. var dat = res.data;
  287. this.param = res.ele;
  288. if (dat.length) {
  289. var regroupData = []; //重组数据
  290. var kindArr = []; //通道数组
  291. var time = [];
  292. var xtitle = [];
  293. for (var i = 0; i < dat.length; i++) {
  294. var item = eval('(' + dat[i] + ')');
  295. console.log(item);
  296. var tim = new Date(item['dataTime']).getTime();
  297. var times = new Date(tim);
  298. xtitle.unshift(
  299. times.getMonth() +
  300. 1 +
  301. '/' +
  302. times.getDate() +
  303. '-' +
  304. times.getHours() +
  305. ':' +
  306. times.getMinutes()
  307. );
  308. time.unshift(tim);
  309. for (var j in item) {
  310. var arr = '';
  311. if (j == 'id' || j == 'dataTime' || j == 'windDir') {
  312. continue;
  313. } else if (kindArr.indexOf(j) == '-1') {
  314. kindArr.push(j);
  315. regroupData.push({
  316. name: this.param[j],
  317. color: this.color[kindArr.length - 1],
  318. data: [],
  319. });
  320. // arr.push(tim);
  321. arr = parseFloat(item[j]);
  322. regroupData[kindArr.indexOf(j)].data.unshift(arr);
  323. } else {
  324. // arr.push(tim);
  325. // arr.push(parseFloat(item[j]));
  326. arr = parseFloat(item[j]);
  327. regroupData[kindArr.indexOf(j)].data.unshift(arr);
  328. }
  329. }
  330. }
  331. console.log(regroupData);
  332. // 分割折线图
  333. const regroupDataNum = Math.ceil(regroupData.length / 2);
  334. const options1 = regroupData.filter((v, i) => {
  335. return i < regroupDataNum;
  336. });
  337. const options2 = regroupData.filter((v, i) => {
  338. return i >= regroupDataNum;
  339. });
  340. console.log(options1, options2);
  341. this.showColumn('canvasColumnA', xtitle, options1);
  342. this.showColumn('canvasColumnB', xtitle, options2);
  343. this.canvastishiTF = true;
  344. } else {
  345. this.canvastishiTF = false;
  346. this.showColumn('canvasColumnA', xtitle, []);
  347. this.showColumn('canvasColumnB', xtitle, []);
  348. }
  349. },
  350. prev() {
  351. //上一页
  352. if (this.page > 1) {
  353. this.page--;
  354. this.histprydatas();
  355. }
  356. },
  357. next() {
  358. //下一页
  359. if (this.page < this.pagesum) {
  360. this.page++;
  361. this.histprydatas();
  362. }
  363. },
  364. clickLeft() {
  365. uni.navigateBack({
  366. delta: 1,
  367. });
  368. },
  369. showColumn(id, xtitle, xinfo) {
  370. console.log(id);
  371. var _self = this;
  372. const ctx = uni.createCanvasContext(id, this);
  373. if (id === 'canvasColumnA') {
  374. canvaColumnA = new uCharts({
  375. context: ctx,
  376. type: 'line',
  377. legend: {
  378. position: 'top',
  379. },
  380. fontSize: 11,
  381. background: '#FFFFFF',
  382. pixelRatio: 1,
  383. animation: true,
  384. dataLabel: false,
  385. categories: xtitle,
  386. series: xinfo,
  387. enableScroll: true, //开启图表拖拽功能
  388. xAxis: {
  389. disableGrid: true,
  390. type: 'grid',
  391. gridType: 'dash',
  392. itemCount: 4, //x轴单屏显示数据的数量,默认为5个
  393. scrollShow: true, //新增是否显示滚动条,默认false
  394. // scrollAlign: 'left', //滚动条初始位置
  395. scrollBackgroundColor: '#F7F7FF', //默认为 #EFEBEF
  396. scrollColor: '#DEE7F7', //默认为 #A6A6A6
  397. },
  398. yAxis: {},
  399. width: _self.cWidth * 1,
  400. height: _self.cHeight * 1,
  401. extra: {
  402. line: {
  403. type: 'curve',
  404. },
  405. },
  406. });
  407. } else if (id === 'canvasColumnB') {
  408. canvaColumnB = new uCharts({
  409. context: ctx,
  410. type: 'line',
  411. legend: {
  412. position: 'top',
  413. },
  414. fontSize: 11,
  415. background: '#FFFFFF',
  416. pixelRatio: 1,
  417. animation: true,
  418. dataLabel: false,
  419. categories: xtitle,
  420. series: xinfo,
  421. enableScroll: true, //开启图表拖拽功能
  422. xAxis: {
  423. disableGrid: true,
  424. type: 'grid',
  425. gridType: 'dash',
  426. itemCount: 4, //x轴单屏显示数据的数量,默认为5个
  427. scrollShow: true, //新增是否显示滚动条,默认false
  428. // scrollAlign: 'left', //滚动条初始位置
  429. scrollBackgroundColor: '#F7F7FF', //默认为 #EFEBEF
  430. scrollColor: '#DEE7F7', //默认为 #A6A6A6
  431. },
  432. yAxis: {},
  433. width: _self.cWidth * 1,
  434. height: _self.cHeight * 1,
  435. extra: {
  436. line: {
  437. type: 'curve',
  438. },
  439. },
  440. });
  441. }
  442. },
  443. touchLineA(e) {
  444. console.log(e);
  445. canvaColumnA.scrollStart(e);
  446. },
  447. moveLineA(e) {
  448. canvaColumnA.scroll(e);
  449. },
  450. touchEndLineA(e) {
  451. canvaColumnA.scrollEnd(e);
  452. //下面是toolTip事件,如果滚动后不需要显示,可不填写
  453. canvaColumnA.showToolTip(e, {
  454. format: function (item, category) {
  455. return category + ' ' + item.name + ':' + item.data;
  456. },
  457. });
  458. },
  459. touchLineB(e) {
  460. console.log(e);
  461. canvaColumnB.scrollStart(e);
  462. },
  463. moveLineB(e) {
  464. canvaColumnB.scroll(e);
  465. },
  466. touchEndLineB(e) {
  467. canvaColumnB.scrollEnd(e);
  468. //下面是toolTip事件,如果滚动后不需要显示,可不填写
  469. canvaColumnB.showToolTip(e, {
  470. format: function (item, category) {
  471. return category + ' ' + item.name + ':' + item.data;
  472. },
  473. });
  474. },
  475. },
  476. onLoad(option) {
  477. this.eqinfo = JSON.parse(option.shebei);
  478. this.basetype = this.eqinfo.type;
  479. this.cWidth = uni.upx2px(650);
  480. this.cHeight = uni.upx2px(500);
  481. this.device_id = option.id;
  482. this.end = parseInt(+new Date() / 1000);
  483. this.begintime = parseInt(this.end - 24 * 60 * 60);
  484. this.histprydatas();
  485. this.getChartLine();
  486. this.kongtf = this.$QueryPermission(347);
  487. this.datatf = this.$QueryPermission(348);
  488. },
  489. };
  490. </script>
  491. <style lang="scss">
  492. .info {
  493. width: 100%;
  494. .info_item {
  495. width: 90%;
  496. margin: 0 auto;
  497. height: 240rpx;
  498. padding: 40rpx 50rpx;
  499. position: relative;
  500. box-sizing: border-box;
  501. .bgi {
  502. width: 100%;
  503. height: 100%;
  504. position: absolute;
  505. top: 0;
  506. left: 0;
  507. z-index: -1;
  508. }
  509. p {
  510. font-size: 24rpx;
  511. color: #ffffff;
  512. margin-bottom: 10rpx;
  513. .tishi {
  514. width: 30rpx;
  515. height: 30rpx;
  516. margin: 0rpx 0 0 20rpx;
  517. }
  518. }
  519. }
  520. }
  521. .control {
  522. width: 90%;
  523. margin-top: 30rpx;
  524. display: flex;
  525. text-align: center;
  526. // padding: 0 30rpx;
  527. box-sizing: border-box;
  528. .control_item {
  529. width: 128rpx;
  530. height: 120rpx;
  531. width: 20%;
  532. image {
  533. width: 70rpx;
  534. height: 70rpx;
  535. }
  536. p {
  537. font-size: 24rpx;
  538. }
  539. }
  540. }
  541. .his_box {
  542. width: 100%;
  543. margin-top: 30rpx;
  544. position: relative;
  545. }
  546. .selecttimes {
  547. width: 90%;
  548. box-shadow: 0 0 10rpx #bcb9ca;
  549. padding: 10rpx 20rpx;
  550. box-sizing: border-box;
  551. margin: 0 auto;
  552. font-size: 28rpx;
  553. .timesbox {
  554. display: flex;
  555. justify-content: space-around;
  556. image {
  557. width: 30rpx;
  558. height: 30rpx;
  559. margin-top: 6rpx;
  560. }
  561. .icon {
  562. color: #949494;
  563. text-align: right;
  564. margin-left: 30rpx;
  565. }
  566. }
  567. ::v-deep .u-calendar__action {
  568. display: flex;
  569. justify-content: space-around;
  570. .u-calendar__action__text {
  571. line-height: 25px;
  572. }
  573. }
  574. }
  575. .shuju_one {
  576. width: 90%;
  577. margin: 20px auto;
  578. box-shadow: 0 0 10rpx #bcb9ca;
  579. padding-top: 20rpx;
  580. height: 1000rpx;
  581. .canvastishi {
  582. font-size: 32rpx;
  583. position: absolute;
  584. top: 50%;
  585. left: 50%;
  586. margin-left: -64rpx;
  587. margin-top: -21rpx;
  588. .dataloading:after {
  589. overflow: hidden;
  590. display: inline-block;
  591. vertical-align: bottom;
  592. animation: ellipsis 2s infinite;
  593. content: '\2026';
  594. }
  595. @keyframes ellipsis {
  596. from {
  597. width: 2px;
  598. }
  599. to {
  600. width: 15px;
  601. }
  602. }
  603. }
  604. }
  605. .condition {
  606. display: flex;
  607. flex-wrap: wrap;
  608. width: 90%;
  609. box-shadow: 0 0 10rpx #bcb9ca;
  610. margin: 0 auto 30rpx;
  611. .scroll-X {
  612. width: 95%;
  613. margin: 20rpx auto;
  614. .tr {
  615. display: flex;
  616. overflow: hidden;
  617. .th,
  618. .td {
  619. display: inline-block;
  620. padding: 5rpx;
  621. width: 300rpx;
  622. text-align: center;
  623. height: 52rpx;
  624. line-height: 52rpx;
  625. border: 2rpx solid #f1f1f1;
  626. }
  627. }
  628. .tr:nth-child(2n-1) {
  629. background-color: #f5fff8;
  630. }
  631. .tr:first-child {
  632. background-color: #57c878;
  633. color: #fff;
  634. }
  635. }
  636. .pagenumber {
  637. display: flex;
  638. margin: 20rpx auto;
  639. button {
  640. width: 150rpx;
  641. height: 50rpx;
  642. line-height: 50rpx;
  643. font-size: 26rpx;
  644. text-align: center;
  645. background-color: #57c878;
  646. color: #ffffff;
  647. }
  648. .pagenumber_page {
  649. width: 100rpx;
  650. height: 50rpx;
  651. line-height: 50rpx;
  652. font-size: 26rpx;
  653. text-align: center;
  654. }
  655. }
  656. }
  657. </style>