PestsStats.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <template>
  2. <div>
  3. <el-breadcrumb separator-class="el-icon-arrow-right">
  4. <el-breadcrumb-item :to="{ path: '/index/cbd' }">物联网虫情测报</el-breadcrumb-item>
  5. <el-breadcrumb-item>害虫统计</el-breadcrumb-item>
  6. </el-breadcrumb>
  7. <div class="equipInfo">
  8. <div class="equipMsg">
  9. <span>设备ID:{{id}}</span>
  10. <span>设备名称:{{equipname || '无'}}</span>
  11. <span>位置:{{equipaddress || '无'}}</span>
  12. </div>
  13. <div class="ctrl-check">
  14. <div class="time-check">
  15. <div>
  16. <el-button
  17. :type="btnSelected == '1'?'primary':'default'"
  18. size="mini"
  19. @click="timeBtnClick(1)"
  20. >24小时</el-button>
  21. <el-button
  22. :type="btnSelected == '2'?'primary':'default'"
  23. size="mini"
  24. @click="timeBtnClick(2)"
  25. >近一月</el-button>
  26. <el-button
  27. :type="btnSelected == '3'?'primary':'default'"
  28. size="mini"
  29. @click="timeBtnClick(3)"
  30. >近半年</el-button>
  31. <el-button
  32. :type="btnSelected == '4'?'primary':'default'"
  33. size="mini"
  34. @click="timeBtnClick(4)"
  35. >近一年</el-button>
  36. <el-date-picker
  37. size="mini"
  38. v-model="timeRange"
  39. type="daterange"
  40. range-separator="至"
  41. start-placeholder="开始日期"
  42. end-placeholder="结束日期"
  43. @change="DateChange"
  44. ></el-date-picker>
  45. </div>
  46. </div>
  47. </div>
  48. </div>
  49. <!-- 自动统计图 -->
  50. <div v-if="viewSwitch">
  51. <div>
  52. <el-row :gutter="10">
  53. <el-col :md="24" :lg="15">
  54. <el-card class="box-card">
  55. <template>
  56. <div class="chartsSelect">
  57. <el-select v-model="viewSwitch2" @change="screenInsect()" size="mini" placeholder="请选择">
  58. <el-option
  59. v-for="item in worms"
  60. :key="item.value"
  61. :label="item.label"
  62. :value="item.value"
  63. ></el-option>
  64. </el-select>
  65. </div>
  66. </template>
  67. <div class="charts">
  68. <highcharts :options="options" v-if="chartsShow"></highcharts>
  69. <div class="noDataClass" v-else>暂无数据</div>
  70. </div>
  71. </el-card>
  72. </el-col>
  73. <el-col :md="24" :lg="9">
  74. <el-card class="box-card">
  75. <div class="pie">
  76. <highcharts :options="options2" v-if="chartsShowA"></highcharts>
  77. <div class="noDataClass" v-else>暂无数据</div>
  78. </div>
  79. </el-card>
  80. </el-col>
  81. </el-row>
  82. </div>
  83. <div class="dataTableSearch">
  84. <!-- <el-button type="primary" size="mini" @click.stop="dowonloadFile">导出</el-button> -->
  85. </div>
  86. <el-card class="box-card">
  87. <el-table :data="currTableData" stripe style="width: 100%">
  88. <el-table-column
  89. v-for="(item,index) in tableHeadTxt"
  90. :key="index"
  91. :prop="item[1]"
  92. :label="item[0]"
  93. >
  94. <template slot-scope="scope">{{scope.row[scope.column.property]}}</template>
  95. </el-table-column>
  96. </el-table>
  97. <el-pagination
  98. v-if="currTableData.length"
  99. background
  100. layout="prev, pager, next"
  101. :page='queryInfo.page'
  102. :total="total"
  103. @prev-click="prevClick"
  104. @next-click="nextClick"
  105. @current-change="changePage">
  106. </el-pagination>
  107. </el-card>
  108. </div>
  109. </div>
  110. </template>
  111. <script>
  112. import t from '../../../assets/ezuikit'
  113. import PestList from './cbd_pest_library.js' //注意路径
  114. export default {
  115. data() {
  116. return {
  117. id: this.$route.query.id,
  118. equipname: this.$route.query.name,
  119. equipaddress:this.$route.query.address,
  120. btnSelected: '3',
  121. allPest: PestList,
  122. currPests:[],
  123. options: {},
  124. options2: {},
  125. options3: {},
  126. options4: {},
  127. equip_name: '',
  128. worms: [
  129. // {
  130. // value: 1,
  131. // label: '蛾子'
  132. // },
  133. // {
  134. // value: 2,
  135. // label: '蚊子'
  136. // }
  137. ],
  138. // 状态信息
  139. equipStatus: {},
  140. //总数据条数
  141. total: 0,
  142. // 自动统计动态表头
  143. tableHeadTxt: [
  144. ['害虫名称', 'name'],
  145. ['害虫数量', 'sum'],
  146. ["统计时间", "time"]
  147. ],
  148. // 表格数据
  149. tableData: [],
  150. currTableData:[],
  151. tableDataA: [],
  152. timeRange: '',
  153. queryInfo: {
  154. begin: '',
  155. end: '',
  156. id: this.$route.query.id,
  157. page: 1
  158. },
  159. viewSwitch: 1,
  160. viewSwitch2: '',
  161. viewSwitch23:'',
  162. // 手动统计表头
  163. tableHeadTxtA: [
  164. ['害虫名称', 'pest_name'],
  165. ['害虫数量', 'pest_num'],
  166. ['作物种类', 'crop_name'],
  167. ['虫害阶段', 'pest_case'],
  168. ['统计时间', 'add_time']
  169. // ["统计时间", "upl_time"]
  170. ],
  171. chartsShow: true, //判断折线图是否为空
  172. chartsShowA: true, //判断统计图是否为空
  173. dropDown: [], //手动统计害虫名称下拉数据
  174. chartsLineShow: true, //判断折线图是否为空
  175. chartsPieShow: true //判断统计图是否为空
  176. }
  177. },
  178. watch: {
  179. viewSwitch(val) {
  180. this.btnSelected = '3'
  181. }
  182. },
  183. created() {
  184. },
  185. mounted() {
  186. this.timeBtnClick(3)
  187. },
  188. methods: {
  189. //筛选时间
  190. timeBtnClick(i) {
  191. this.btnSelected = i
  192. this.timeRange = ''
  193. if (i == 1) {
  194. this.queryInfo.begin = new Date(Date.now()- 24 * 3600000).toLocaleDateString().replace(/\//g,'-');
  195. this.queryInfo.end = new Date().toLocaleDateString().replace(/\//g,'-');
  196. } else if (i == 2) {
  197. this.queryInfo.begin = new Date(Date.now()- 24 * 3600000 * 30).toLocaleDateString().replace(/\//g,'-');
  198. this.queryInfo.end = new Date().toLocaleDateString().replace(/\//g,'-');
  199. } else if (i == 3) {
  200. this.queryInfo.begin = new Date(Date.now()- 24 * 3600000 * 30 * 6).toLocaleDateString().replace(/\//g,'-');
  201. this.queryInfo.end = new Date().toLocaleDateString().replace(/\//g,'-');
  202. } else if (i == 4) {
  203. this.queryInfo.begin = new Date(Date.now()- 24 * 3600000 * 30 * 12).toLocaleDateString().replace(/\//g,'-');
  204. this.queryInfo.end = new Date().toLocaleDateString().replace(/\//g,'-');
  205. }
  206. this.getPestChartLine()
  207. },
  208. //获取折线图数据
  209. getPestChartLine() {
  210. this.$axios({
  211. method: 'POST',
  212. url: '/pest_at_ah_1',
  213. data: this.qs.stringify({
  214. e_id: this.queryInfo.id,
  215. tbegin: this.queryInfo.begin,
  216. tend: this.queryInfo.end,
  217. })
  218. }).then((res) => {
  219. this.disposeData(res.data)
  220. this.getTableList(res.data)
  221. })
  222. },
  223. // 处理返回数据格式 害虫数据格式[[[23432456,34],[23432421,3]],[[23432456,35],[23432421,76]]]
  224. disposeData(data) {
  225. var kind = data.kind;
  226. var worm = [];
  227. var atData = [];
  228. var ahData = [];
  229. // 折线
  230. var wormsArr = [];
  231. var html = '';
  232. var kind=kind.filter(function (item) {
  233. return item!='0';
  234. });
  235. if (!kind.length) {
  236. this.worms = [];
  237. this.viewSwitch2 = ''
  238. this.chartsShow = false;
  239. this.chartsShowA = false;
  240. }
  241. for (var z = 0; z < kind.length; z++) {
  242. wormsArr.push({
  243. value:z,
  244. label:this.allPest[kind[z]]
  245. })
  246. if (z == kind.length - 1) {
  247. this.worms = wormsArr;
  248. }
  249. }
  250. for (var i = 0; i < data.dat1.length; i++) {
  251. var arr1 = [],
  252. arr2 = [];
  253. if(parseFloat((data.dat1[i].at / 10).toFixed(1)) != '25'){
  254. arr1.push(this.returnTime(data.dat1[i].time));
  255. arr1.push(parseFloat((data.dat1[i].at / 10).toFixed(1)));
  256. }else{
  257. arr1.push(this.returnTime(data.dat1[i].time));
  258. arr1.push(0);
  259. }
  260. if(parseFloat((data.dat1[i].ah / 10).toFixed(1)) != '30'){
  261. arr2.push(this.returnTime(data.dat1[i].time));
  262. arr2.push(parseFloat((data.dat1[i].ah / 10).toFixed(1)));
  263. }else{
  264. arr2.push(this.returnTime(data.dat1[i].time));
  265. arr2.push(0);
  266. }
  267. atData.unshift(arr1);
  268. ahData.unshift(arr2);
  269. if (i == data.dat1.length - 1) {
  270. if (data.dat.length) {
  271. for (var j = 0; j < data.dat.length; j++) {
  272. if(data.dat[j].result == '0'){
  273. if (j == data.dat.length - 1) {
  274. this.currPests = worm
  275. this.currAtData = atData
  276. this.currAhData = ahData
  277. this.currWorm = worm
  278. this.currKind = kind
  279. this.chartLineInit(atData,ahData,worm[0],this.allPest[kind[0]])
  280. this.chartsShow = true;
  281. this.viewSwitch2 = this.allPest[kind[0]]
  282. var drawPieChartData = [];
  283. // 饼状图
  284. for (var ss = 0; ss < worm.length; ss++) {
  285. var currWormTotal = 0;
  286. console.log(ss)
  287. console.log(worm)
  288. console.log(worm[ss])
  289. for (var sss = 0; sss < worm[ss].length; sss++) {
  290. currWormTotal += worm[ss][sss][1];
  291. if (sss == worm[ss].length - 1) {
  292. drawPieChartData.push({
  293. name: this.allPest[kind[ss]],
  294. key: ss,
  295. y: currWormTotal
  296. })
  297. }
  298. }
  299. if (ss == worm.length - 1) {
  300. this.chartPieInit(drawPieChartData)
  301. this.chartsShowA = true;
  302. }
  303. }
  304. }
  305. continue;
  306. }
  307. var secondArr = [];
  308. var currTime = this.returnTime(data.dat[j].time)
  309. var resultArr = data.dat[j].result.split('#');
  310. for (var z = 0; z < resultArr.length; z++) {
  311. var thirdlyArr = [];
  312. var wormNameNum = resultArr[z].split(',')[0];
  313. var wormValNum = parseInt(resultArr[z].split(',')[1]);
  314. thirdlyArr.push(currTime)
  315. thirdlyArr.push(wormValNum);
  316. var wormIndex = kind.indexOf(wormNameNum);
  317. if (worm[wormIndex]) {
  318. worm[wormIndex].unshift(thirdlyArr);
  319. } else {
  320. worm[wormIndex] = [thirdlyArr];
  321. }
  322. }
  323. console.log(j);
  324. if (j == data.dat.length - 1) {
  325. this.currPests = worm
  326. this.currAtData = atData
  327. this.currAhData = ahData
  328. this.currWorm = worm
  329. this.currKind = kind
  330. this.chartLineInit(atData,ahData,worm[0],this.allPest[kind[0]])
  331. this.chartsShow = true;
  332. this.viewSwitch2 = this.allPest[kind[0]]
  333. var drawPieChartData = [];
  334. // 饼状图
  335. for (var ss = 0; ss < worm.length; ss++) {
  336. var currWormTotal = 0;
  337. console.log(ss)
  338. console.log(worm)
  339. console.log(worm[ss])
  340. for (var sss = 0; sss < worm[ss].length; sss++) {
  341. currWormTotal += worm[ss][sss][1];
  342. if (sss == worm[ss].length - 1) {
  343. drawPieChartData.push({
  344. name: this.allPest[kind[ss]],
  345. key: ss,
  346. y: currWormTotal
  347. })
  348. }
  349. }
  350. if (ss == worm.length - 1) {
  351. this.chartPieInit(drawPieChartData)
  352. this.chartsShowA = true;
  353. }
  354. }
  355. }
  356. }
  357. } else {
  358. this.chartLineInit([],[],[],'')
  359. this.chartPieInit([])
  360. this.chartsShow = false;
  361. this.chartsShowA = false;
  362. }
  363. }
  364. }
  365. if (data.dat1.length == 0) {
  366. this.chartLineInit([],[],[],'')
  367. this.chartPieInit([])
  368. this.chartsShow = false;
  369. this.chartsShowA = false;
  370. }
  371. },
  372. // 返回时间戳
  373. returnTime(time) {
  374. var thisTime = time.replace(/-/g, '/');
  375. var time = new Date(thisTime);
  376. var timestamp = time.getTime() + 8 * 3600000;
  377. return timestamp;
  378. },
  379. DateChange() {
  380. console.log(this.timeRange)
  381. this.btnSelected = null;
  382. this.queryInfo.page = 1;
  383. if(this.timeRange){
  384. this.queryInfo.begin = new Date(this.timeRange[0]).toLocaleDateString().replace(/\//g,'-');
  385. this.queryInfo.end = new Date(this.timeRange[1]).toLocaleDateString().replace(/\//g,'-');
  386. }else{
  387. this.queryInfo.begin = '';
  388. this.queryInfo.end = '';
  389. }
  390. this.getPestChartLine()
  391. },
  392. //折线图初始化
  393. chartLineInit(atData,ahData,worm,wormName){
  394. this.options = {
  395. chart: {
  396. zoomType: 'x'
  397. },
  398. title: {
  399. text: '害虫变化趋势',
  400. align: 'left'
  401. },
  402. subtitle: {
  403. text: ''
  404. },
  405. xAxis: {
  406. crosshair: true, //十字基准线
  407. type: 'datetime',
  408. dateTimeLabelFormats: {
  409. //根据时间间距X轴自动显示哪种格式
  410. millisecond: '%H:%M:%S.%L',
  411. second: '%H:%M:%S',
  412. minute: '%H:%M',
  413. hour: '%H:%M',
  414. day: '%m-%d',
  415. week: '%m-%d',
  416. month: '%Y-%m',
  417. year: '%Y'
  418. }
  419. },
  420. yAxis: {
  421. title: {
  422. text: ''
  423. }
  424. },
  425. legend: {
  426. // layout: 'vertical',
  427. align: 'center',
  428. verticalAlign: 'top'
  429. },
  430. plotOptions: {
  431. series: {
  432. label: {
  433. connectorAllowed: false
  434. },
  435. pointStart: 2010
  436. }
  437. },
  438. series: [
  439. {
  440. name: '环境温度',
  441. data: atData
  442. },
  443. {
  444. name: '环境湿度',
  445. data: ahData
  446. },
  447. {
  448. name: wormName,
  449. data: worm
  450. }
  451. ],
  452. colors: ['#00e29d', '#6cbbff', '#ff3f3f'],
  453. credits: {
  454. //去掉默认的highcharts.com
  455. enabled: false
  456. },
  457. tooltip: {
  458. // crosshairs: true,
  459. shared: true, //折线共享
  460. headerFormat: '<b>{point.x:%Y-%m-%e %H:%M:%S}</b><br>'
  461. },
  462. responsive: {
  463. rules: [
  464. {
  465. condition: {
  466. maxWidth: 500
  467. },
  468. chartOptions: {
  469. legend: {
  470. layout: 'horizontal',
  471. align: 'center',
  472. verticalAlign: 'bottom'
  473. }
  474. }
  475. }
  476. ]
  477. }
  478. }
  479. },
  480. //饼状图初始化
  481. chartPieInit(arr) {
  482. var _this = this
  483. this.options2 = {
  484. chart: {
  485. type: 'pie',
  486. options3d: {
  487. enabled: true,
  488. alpha: 60,
  489. beta: 0
  490. }
  491. },
  492. credits: {
  493. enabled: false
  494. },
  495. title: {
  496. text: '害虫比例',
  497. align: 'left'
  498. },
  499. tooltip: {
  500. headerFormat: '{series.name}<br>',
  501. pointFormat: '{point.name}: <b>{point.y}头</b>'
  502. },
  503. colors: ['#00e29d', '#6cbbff', '#ff3f3f'],
  504. plotOptions: {
  505. pie: {
  506. allowPointSelect: true,
  507. cursor: 'pointer',
  508. dataLabels: {
  509. enabled: true,
  510. format: '<b>{point.name}</b>: {point.percentage:.1f} %'
  511. },
  512. point: {
  513. events: {
  514. mouseOver: function (e) {
  515. // 鼠标滑过时动态更新标题
  516. // console.log(e)
  517. // console.log(this.setTitle())
  518. // 标题更新函数,API 地址:https://api.hcharts.cn/highcharts#Chart.setTitle
  519. // VueHighcharts.setTitle({
  520. // text: e.target.name+ '\t'+ e.target.y + ' %'
  521. // });
  522. },
  523. click(e) {
  524. // 同样的可以在点击事件里处理
  525. _this.viewSwitch2 = e.point.key;
  526. _this.screenInsect()
  527. }
  528. }
  529. }
  530. }
  531. },
  532. series: [
  533. {
  534. type: 'pie',
  535. innerSize: '80%',
  536. name: '害虫比例',
  537. data: arr
  538. }
  539. ]
  540. },
  541. function (c) {
  542. // 图表初始化完毕后的会掉函数
  543. // 环形图圆心
  544. var centerY = c.series[0].center[1],
  545. titleHeight = parseInt(c.title.styles.fontSize)
  546. // 动态设置标题位置
  547. c.setTitle({
  548. y: centerY + titleHeight / 2
  549. })
  550. }
  551. },
  552. //获取表格历史数据
  553. getTableList(data) {
  554. console.log(data)
  555. var dat = data.dat;
  556. var arr = [];
  557. for(var i = 0;i<dat.length;i++){
  558. var result = dat[i].result.split('#');
  559. for(var j = 0;j<result.length;j++){
  560. if(result[j] == '0'){
  561. continue;
  562. }
  563. var resultItem = result[j].split(',');
  564. arr.push({
  565. name:this.allPest[resultItem[0]],
  566. sum:resultItem[1],
  567. time:dat[i].time
  568. })
  569. }
  570. }
  571. this.tableData = arr;
  572. this.total = this.tableData.length;
  573. this.currTableData = this.tableData.slice((this.queryInfo.page-1)*10,this.queryInfo.page*10)
  574. },
  575. prevClick(val){
  576. this.queryInfo.page--;
  577. this.currTableData = this.tableData.slice((this.queryInfo.page-1)*10,this.queryInfo.page*10)
  578. },
  579. nextClick(val){
  580. this.queryInfo.page++;
  581. this.currTableData = this.tableData.slice((this.queryInfo.page-1)*10,this.queryInfo.page*10)
  582. },
  583. //改变page
  584. changePage(val){
  585. this.queryInfo.page=val;
  586. this.currTableData = this.tableData.slice((this.queryInfo.page-1)*10,this.queryInfo.page*10)
  587. },
  588. // 下拉框筛选害虫名称
  589. screenInsect() {
  590. this.chartLineInit(this.currAtData,this.currAhData,this.currWorm[this.viewSwitch2],this.allPest[this.currKind[this.viewSwitch2]])
  591. },
  592. // 下载
  593. dowonloadFile(){
  594. window.location.href = '/pest_export?id=' + this.id + ' &filename="pestFile"'
  595. },
  596. }
  597. }
  598. </script>
  599. <style lang='less' scoped>
  600. .box-card {
  601. position: relative;
  602. }
  603. .equipInfo {
  604. .equipMsg {
  605. font-size: 14px;
  606. color: #3d3d3d;
  607. i {
  608. font-size: 16px;
  609. color: #14a478;
  610. }
  611. span {
  612. margin-left: 5px;
  613. }
  614. }
  615. display: flex;
  616. justify-content: space-between;
  617. margin-bottom: 15px;
  618. }
  619. .time-check {
  620. display: flex;
  621. justify-content: space-between;
  622. .el-input__inner {
  623. margin-left: 10px;
  624. width: 222px;
  625. }
  626. .viewSwitch {
  627. margin-left: 10px;
  628. }
  629. }
  630. .chartsSelect {
  631. text-align: right;
  632. position: absolute;
  633. z-index: 31;
  634. left: 0;
  635. right: 21px;
  636. }
  637. .charts,
  638. .pie {
  639. height: 423px;
  640. }
  641. .equipStatus {
  642. display: flex;
  643. margin: 10px 0;
  644. .equipIcon {
  645. margin: 0 10%;
  646. }
  647. .equipParams {
  648. min-width: 80px;
  649. line-height: 27px;
  650. p {
  651. color: #a6a6a6;
  652. }
  653. }
  654. }
  655. .dataTableSearch {
  656. display: flex;
  657. justify-content: space-between;
  658. margin: 20px 0;
  659. .el-input__inner {
  660. width: 222px;
  661. }
  662. }
  663. // .check-btns{display:flex;justify-content: space-between;margin-bottom:20px}
  664. .echarts {
  665. width: 100%;
  666. height: 300px;
  667. }
  668. // 暂无数据
  669. .noDataClass {
  670. text-align: center;
  671. font-size: 25px;
  672. line-height: 450px;
  673. color: rgb(122, 115, 115);
  674. }
  675. </style>