barChart.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. <template>
  2. <div :id="chartId" class="linechart">
  3. </div>
  4. </template>
  5. <script>
  6. import echarts from "echarts";
  7. import moment from "moment"
  8. export default {
  9. props:{
  10. chartId:String,
  11. chartDate:{
  12. default:null
  13. },
  14. xType:String,
  15. normalChart:{
  16. type:Boolean,
  17. default:false,
  18. },
  19. weekNormalChart:{
  20. type:Boolean,
  21. default:false,
  22. },
  23. numberChart:{
  24. // type:Boolean,
  25. default:false,
  26. },
  27. yType:{
  28. type:String,
  29. default:"rate"
  30. },
  31. sjChartType:{
  32. type:String
  33. },
  34. envType:{
  35. type:String,
  36. default:'Tdb'
  37. },
  38. tempColor:{
  39. default:false
  40. }
  41. },
  42. data(){
  43. return {
  44. chartInit:null,
  45. envMap:{
  46. 'Tdb':{
  47. name:'温度',
  48. unit:"°C",
  49. color:"#0091FF",
  50. avg:"avgTemp",
  51. param:[
  52. {name:"偏冷占比",numName:"偏冷",color:"#0091FF",key:"coldProprotion"},
  53. {name:"达标占比",numName:"达标",color:"#ffffff",key:"normalProprotion",centerShow:true},
  54. {name:"偏热占比",numName:"偏热",color:"#F9908B",key:"hotProprotion"},
  55. ]
  56. },
  57. 'CO2':{
  58. name:'CO₂',
  59. unit:"ppm",
  60. color:"#2EA121",
  61. avg:"avgCo2",
  62. param:[
  63. {name:"正常",color:"#ffffff",key:"co2NormalProprotion",centerShow:true},
  64. {name:"超标",color:"#DCAA04",key:"co2AbNormalProprotion"},
  65. ]
  66. },
  67. 'HCHO':{
  68. name:'甲醛',
  69. unit:"mg/m³",
  70. color:"#2EA121",
  71. avg:"avgHcho",
  72. param:[
  73. {name:"正常",color:"#ffffff",key:"hchoNormalProprotion",centerShow:true},
  74. {name:"超标",color:"#C6322B",key:"hchoAbNormalProprotion"},
  75. ]
  76. },
  77. 'RH':{
  78. name:'相对湿度',
  79. unit:"%",
  80. color:"#2EA121",
  81. avg:"avgRh",
  82. param:[
  83. {name:"偏湿",color:"#0091FF",key:"rhPartialHumidityProprotion"},
  84. {name:"正常",color:"#ffffff",key:"rhNormalProprotion",centerShow:true},
  85. {name:"偏干",color:"#F58300",key:"rhPartialDryProprotion"},
  86. ]
  87. },
  88. 'PM2d5':{
  89. name:'PM2.5',
  90. unit:"μg/m³",
  91. color:"#2EA121",
  92. avg:"avgPm2d5",
  93. param:[
  94. {name:"正常",color:"#ffffff",key:"pm2d5NormalProprotion",centerShow:true},
  95. {name:"超标",color:"#dcaa04",key:"pm2d5AbNormalProprotion"},
  96. ]
  97. },
  98. 'userAdjust':{
  99. name:'用户调节',
  100. unit:"个",
  101. color:"#2EA121",
  102. avg:"",
  103. param:[
  104. // {name:"正常调节",color:"#2EA121",key:"feedbackNorSpaceNum"},
  105. {name:"无用户调节",color:"#ffffff",key:"feedbackNoSpaceNum",centerShow:true},
  106. {name:"用户调节",color:"#F9908B",key:"feedbackAbnorSpaceNum"},
  107. ]
  108. },
  109. 'energyManage':{
  110. name:'能源管理',
  111. unit:"kWh",
  112. color:"#2EA121",
  113. avg:"",
  114. param:[
  115. {name:"日能耗",color:"#2EA121",key:"energy"},
  116. ]
  117. },
  118. 'Num':{
  119. name:'温度',
  120. unit:"°C",
  121. color:"#0091FF",
  122. avg:"avgTemp",
  123. param:[
  124. {name:"偏冷数量",color:"#0091FF",key:"coldSpaceNum"},
  125. {name:"达标数量",color:"#ffffff",key:"normalSpaceNum",centerShow:true},
  126. {name:"偏热数量",color:"#F9908B",key:"hotSpaceNum"},
  127. ]
  128. },
  129. },
  130. }
  131. },
  132. mounted(){
  133. this.$once("hook:beforeDestroy", () => {
  134. if (this.chartInit) {
  135. this.chartInit.clear();
  136. }
  137. })
  138. },
  139. methods:{
  140. moment,
  141. showChartInfo(divId, infoStr="暂无数据"){
  142. let msgOption = {
  143. title: {
  144. show: true,
  145. textStyle:{
  146. color:'grey',
  147. fontSize:14
  148. },
  149. text: infoStr,
  150. left: 'center',
  151. top: 'center'
  152. },
  153. xAxis: {
  154. show: false
  155. },
  156. yAxis: {
  157. show: false
  158. },
  159. series: []
  160. };
  161. this.chartInit= echarts.init(document.getElementById(divId));
  162. this.chartInit.hideLoading()
  163. this.chartInit.setOption(msgOption)
  164. },
  165. initDayTime(value){
  166. value =value.slice(4,6)+'-'+ value.slice(6,8)
  167. return value
  168. },
  169. initHourTime(value){
  170. value =value.slice(0,2)+':'+ value.slice(2,4)
  171. return value
  172. },
  173. drawChart(id = this.chartId,data={}){
  174. if(!data||!Object.keys(data).length){
  175. this.showChartInfo(id);
  176. return
  177. }
  178. let that=this;
  179. this.chartInit&&(this.chartInit=null)
  180. this.chartInit= echarts.init(document.getElementById(id));
  181. let dataX;
  182. if(this.xType=="day"){
  183. dataX=data.date||[];
  184. }else if(this.xType=="hour"){
  185. dataX=data.time||[];
  186. }else{
  187. dataX=data.floorName||[];
  188. }
  189. let option = {
  190. tooltip: {
  191. trigger: 'axis',
  192. axisPointer: { // 坐标轴指示器,坐标轴触发有效
  193. type: '' // 默认为直线,可选为:'line' | 'shadow'
  194. },
  195. formatter: params=> {
  196. var showHtm="";
  197. let name = params[0].name;
  198. let scale=100;
  199. let fixed=1;
  200. let unit ='%';
  201. if(this.numberChart){
  202. scale=1;
  203. fixed=0;
  204. unit=this.envMap[envType].unit||'个';
  205. }
  206. if(this.xType&&this.xType!=="floor"){
  207. name = this.xType=="day"?this.initDayTime(params[0].name):this.initHourTime(params[0].name)
  208. }
  209. for(var i=0;i<params.length;i++){
  210. //名称
  211. var text = params[i].marker +params[i].seriesName;
  212. //值
  213. var value = (params[i].value||params[i].value==0)?params[i].value:'--';
  214. value = this.yType=="rate"?(value!=='--'?((value*scale).toFixed(fixed)+unit):'--'):value;
  215. showHtm+= text+ ':' + value +'<br>'
  216. }
  217. showHtm =`${name}<br/>${showHtm}`;
  218. return showHtm;
  219. }
  220. },
  221. grid: {
  222. left: "50",
  223. right:(this.envType=="PM2d5"||this.envType=="HCHO"||this.envType=="CO2")?"60":"50",
  224. bottom: "30",
  225. top:"7",
  226. borderColor:'#E9E9E9',
  227. },
  228. color: ['#0091FF','#FFFFFF','#F9908B'],
  229. animation:false,
  230. xAxis: {
  231. type: 'category',
  232. // boundaryGap: false,
  233. data: dataX,
  234. axisTick:{
  235. show:false
  236. },
  237. interval:0,
  238. axisLine:{
  239. lineStyle:{
  240. color:'#D9D9D9',
  241. // width:8,//这里是为了突出显示加上的
  242. }
  243. },
  244. axisLabel: {
  245. color:'#848484',
  246. interval:0,
  247. fontSize:11,
  248. formatter:(value)=>{
  249. if(this.xType=="hour"&&value.endsWith("0000")){
  250. return value.slice(0,2)+':'+value.slice(2,4)
  251. }else if(this.xType=="hour"&&!value.endsWith("0000")){
  252. return ''
  253. }
  254. if(this.xType=="day"){
  255. return value.slice(4,6)+'-'+value.slice(6,8)+'\n'+'周'+this.getWeek(moment(value).format('E'))
  256. }else{
  257. return value
  258. }
  259. // !this.normalChart&&(value = value*100+'%');
  260. }
  261. },
  262. },
  263. yAxis: {
  264. type: 'value',
  265. position:'left',
  266. axisLabel: {
  267. color:'#848484',
  268. fontSize:12,
  269. formatter:(value,index)=>{
  270. if(index%2!==0&&this.numberChart){
  271. return '';
  272. }
  273. if(!this.normalChart&&!this.numberChart){
  274. value = value*100+'%'
  275. }
  276. return value
  277. }
  278. },
  279. splitLine: {
  280. show: false,
  281. lineStyle:{
  282. color: ['#E9E9E9'],
  283. width: 1,
  284. type: 'dashed'
  285. }
  286.   },
  287. nameTextStyle:{
  288. color:'#848484'
  289. },
  290. axisTick: {
  291. show: false
  292. },
  293. axisLine: {
  294. show: false
  295. },
  296. },
  297. series: []
  298. };
  299. let envType = this.yType!=="rate"?"Num":this.envType;
  300. this.envMap[envType].param.forEach(item=>{
  301. let obj= {
  302. name: item.name,
  303. type: 'bar',
  304. stack: '达标率',
  305. data: data[item.key],
  306. barWidth: '50%',
  307. barMaxWidth:'50',
  308. color:item.color
  309. };
  310. if(item.centerShow){
  311. obj.itemStyle={barBorderColor: '#D6DADF'};
  312. obj.label={
  313. normal: {
  314. show: (this.yType=="rate"&&this.xType=='day'||(this.sjChartType))?true:false,
  315. position: 'inside',
  316. color:"#1F2329",
  317. formatter: (params)=>{
  318. if(this.numberChart){
  319. return !params.value?'':params.value;
  320. }
  321. return !params.value?'':`${parseInt(params.value*100)}%`;
  322. }
  323. },
  324. }
  325. }
  326. option.series.push(obj)
  327. })
  328. // 各房间日均温度分布
  329. if(this.normalChart){
  330. // ["<=23","23~24","24~25","25~26","26~27",">27"]
  331. // let normalDatex=["≤18","18<X≤20","20<X≤22","22<X≤24","24<X≤26","26<X≤28","X>28"];
  332. let normalDatex=["≤18","18~20","20~22","22~24","24~26","26~28","X>28"];
  333. option.xAxis.data=normalDatex;
  334. option.grid.top="45"
  335. option.title={
  336. subtext: '空间数量'
  337. }
  338. option.series=[];
  339. option.series=[
  340. {name: '空间数量',
  341. type: 'bar',
  342. stack: '达标率',
  343. color:"#82c7fc",
  344. barWidth: '30%',
  345. data: []
  346. }
  347. ]
  348. if(this.tempColor){
  349. option.series[0].itemStyle= {
  350. normal:{
  351. color: function (params){
  352. let colorList =["#4a88c0","#adcce9","#ffffff","#ffffff","#ffffff","#f5b588","#ff0000"];
  353. return colorList[params.dataIndex];
  354. },
  355. barBorderColor: '#eaeaea',
  356. borderType : 'solid',
  357. borderWidth:1,
  358. },
  359. //鼠标悬停时:
  360. emphasis: {
  361. barBorderColor: '#eaeaea',
  362. borderType : 'solid',
  363. borderWidth:1,
  364. }
  365. };
  366. };
  367. if(data[0]){
  368. option.series[0].data=[data[0].oneSpaceNum,data[0].twoSpaceNum,data[0].threeSpaceNum,data[0].fourSpaceNum,data[0].fiveSpaceNum,data[0].sixSpaceNum,data[0].sevenSpaceNum];
  369. }
  370. }
  371. // 各达标区间空间数量分布
  372. if(this.weekNormalChart){
  373. // ["≥90%","80%~90%","70%~80%","<70%"]
  374. let normalDatex=["90~100","80~90","70~80","60~70","50~60","40~50","30~40","20~30","10~20","0~10"];
  375. option.xAxis.data=normalDatex;
  376. option.xAxis.name="达标区间(%)";
  377. option.xAxis.nameTextStyle={
  378. color:"#aaaaaa"
  379. }
  380. option.yAxis.show=false;
  381. // option.grid.top="45"
  382. option.title={
  383. subtext: '空间数量'
  384. }
  385. option.grid= {
  386. top:"18",
  387. left: "50",
  388. right: "65",
  389. right: "500",
  390. bottom: "30",
  391. };
  392. option.series=[];
  393. option.series=[
  394. {name: '空间数量',
  395. type: 'bar',
  396. stack: '数量',
  397. // color:"#82c7fc",
  398. barWidth: '50%',
  399. itemStyle: {
  400. //通常情况下:
  401. normal:{
  402.             //每个柱子的颜色即为colorList数组里的每一项,如果柱子数目多于colorList的长度,则柱子颜色循环使用该数组
  403. color: function (params){
  404. // var colorList = ['#0091FF','#0091FF','#0091FF','#0091FF'];
  405. let colorList =["#ffffff","#f2f2f2","#d9d9d9","#bfbfbf","#ff0000","#ff0000","#ff0000","#ff0000","#ff0000","#ff0000"];
  406. return colorList[params.dataIndex];
  407. },
  408. barBorderColor: '#eaeaea',
  409. borderType : 'solid',
  410. borderWidth:1
  411. },
  412. //鼠标悬停时:
  413. emphasis: {
  414. barBorderColor: '#eaeaea',
  415. borderType : 'solid',
  416. borderWidth:1,
  417. // shadowBlur: 10,
  418. // shadowOffsetX: 0,
  419. // shadowColor: 'rgba(0, 145, 255, 0.5)'
  420. }
  421. },
  422. label: {
  423. normal: {
  424. show: true,
  425. position: 'top',
  426. color:"#1F2329",
  427. formatter: (params)=>{
  428. return `${parseInt(params.value)}`
  429. }
  430. },
  431. },
  432. data: []
  433. }
  434. ]
  435. if(data){
  436. option.series[0].data=[
  437. data.oneSpaceNum,data.twoSpaceNum,data.threeSpaceNum,data.fourSpaceNum,data.fiveSpaceNum,
  438. data.sixSpaceNum,data.sevenSpaceNum,data.eightSpaceNum,data.nineSpaceNum,data.tenSpaceNum
  439. ];
  440. }
  441. }
  442. if(this.numberChart){
  443. option.grid.top="22"
  444. option.title={
  445. top:-13,
  446. left:0,
  447. subtext: '空间数量'
  448. }
  449. if(this.envType==="energyManage"){
  450. option.title={
  451. top:-13,
  452. left:12,
  453. subtext: 'kWh'
  454. };
  455. option.series[0].label= {
  456. normal: {
  457. show: true,
  458. position: 'top',
  459. color:"#1F2329",
  460. formatter: (params)=>{
  461. return `${parseInt(params.value)}`
  462. }
  463. },
  464. };
  465. option.series[0].itemStyle= {
  466. normal:{
  467. color: function (params){
  468. if(params.dataIndex<7){
  469. return '#D6DADF'
  470. }
  471. return '#BCBFC2'
  472. },
  473. barBorderColor: '#eaeaea',
  474. borderType : 'solid',
  475. borderWidth:1,
  476. },
  477. //鼠标悬停时:
  478. emphasis: {
  479. barBorderColor: '#eaeaea',
  480. borderType : 'solid',
  481. borderWidth:1,
  482. }
  483. };
  484. }
  485. }
  486. if(this.sjChartType){
  487. if(this.sjChartType=="regions"){
  488. let normalDatex=["内区","外区"];
  489. option.xAxis.data=normalDatex;
  490. }
  491. if(this.sjChartType=="orientation"){
  492. let normalDatex=["东","南","西","北"];
  493. option.xAxis.data=normalDatex;
  494. }
  495. if(this.sjChartType=="localtion" || this.sjChartType=="freshAir" ){
  496. let normalDatex=data.objectName;
  497. option.xAxis.data=normalDatex;
  498. }
  499. option.yAxis.show=false;
  500. option.grid= {
  501. left: "0",
  502. right: "0",
  503. bottom: "30",
  504. top:"7",
  505. borderColor:'#E9E9E9',
  506. };
  507. }
  508. this.chartInit.setOption(option);
  509. window.addEventListener("resize",function(){
  510. that.chartInit.resize();
  511. })
  512. },
  513. getWeek (week) {
  514. switch (Number(week)) {
  515. case 1:
  516. return '一'
  517. case 2:
  518. return '二'
  519. case 3:
  520. return '三'
  521. case 4:
  522. return '四'
  523. case 5:
  524. return '五'
  525. case 6:
  526. return '六'
  527. case 7:
  528. return '日'
  529. default:
  530. return '--'
  531. }
  532. },
  533. },
  534. watch:{
  535. chartDate:{
  536. handler(newval){
  537. if (this.chartInit) {
  538. this.chartInit.clear();
  539. }
  540. this.chartDate=newval;
  541. this.$nextTick(()=>{
  542. this.drawChart(this.chartId,this.chartDate)
  543. })
  544. },
  545. deep:true,
  546. immediate: true,
  547. },
  548. envType(n){
  549. this.envType=n;
  550. console.log(this.envType,"this.envType")
  551. if (this.chartInit) {
  552. this.chartInit.clear();
  553. }
  554. this.drawChart(this.chartId,this.chartDate)
  555. }
  556. }
  557. }
  558. </script>
  559. <style lang="less" scoped>
  560. .linechart{
  561. width: 100%;
  562. height: 240px;
  563. }
  564. </style>