devChart.js 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. app.controller('devChartCtrl', ['$scope', '$http', '$timeout', '$interval', 'toaster', 'chartOptions', '$localStorage', function ($scope, $http, $timeout, $interval, toaster, chartOptions, $localStorage) {
  2. particlesJS.load('particles-js', '/1.0/vendor/libs/particles.json', function () {
  3. });
  4. //每4个字自动换行
  5. function autoBreak(str) {
  6. var lineNumber = 4;
  7. var w = $(window).width()
  8. if (w <= 1366) {
  9. lineNumber = 3
  10. } else if (w <= 1920) {
  11. lineNumber = 4
  12. } else if (w <= 4096) {
  13. lineNumber = 8
  14. }
  15. var newStr = '';
  16. for (var index = 0; index < str.length; index++) {
  17. var item = str[index]
  18. newStr = newStr + item
  19. if ((index + 1) % lineNumber === 0) {
  20. newStr = newStr + '\n'
  21. }
  22. }
  23. return newStr
  24. }
  25. /*******以下为echarts*********/
  26. var devChartPanelMap = echarts.init(document.getElementById('devChartPanelMap'));
  27. var incomeChartLine = echarts.init(document.getElementById('incomeChartLine'));
  28. var consumeChartLine = echarts.init(document.getElementById('consumeChartLine'));
  29. var userChartPie = echarts.init(document.getElementById('userChartPie'));
  30. var feedbackChartPie = echarts.init(document.getElementById('feedbackChartPie'));
  31. var dealerIncomeTopChart = echarts.init(document.getElementById('dealerIncomeTopChart'));
  32. var rightChart1 = echarts.init(document.getElementById('rightChart1'));
  33. var devBeingUsedChart = echarts.init(document.getElementById('devBeingUsedChart'));
  34. function resizeChart() {
  35. clearTimeout(timer);
  36. // resize有尺寸改变完后会有一定的延迟,会导致echarts提前渲染,依然是按照原来的尺寸渲染
  37. timer = setTimeout(function () {
  38. devChartPanelMap.resize();
  39. incomeChartLine.resize();
  40. consumeChartLine.resize();
  41. userChartPie.resize();
  42. feedbackChartPie.resize();
  43. dealerIncomeTopChart.resize();
  44. rightChart1.resize();
  45. devBeingUsedChart.resize();
  46. }, 300);
  47. }
  48. $scope.showData = {
  49. devBusy: 0,
  50. devOnline: 0,
  51. devOffline: 0,
  52. unregistered: 0
  53. };
  54. $interval(function () {
  55. setMapTime();
  56. }, 1000);
  57. function setMapTime() {
  58. $scope.showData.date = moment().format("YYYY年MM月DD日")
  59. $scope.showData.week = moment().format('dddd')
  60. $scope.showData.time = moment().format("HH:mm:ss")
  61. }
  62. setMapTime();
  63. var timer = null;
  64. //resize事件绑定
  65. $(window).off("resize.devChart").on("resize.devChart", function () {
  66. resizeChart();
  67. });
  68. var colorStopList = {
  69. blue: ['#57FFE0', '#3469E2'],
  70. red: ['#FF7671', '#A14AFF'],
  71. yellow: ['#FFEA4F', '#F89212'],
  72. green: ['#61E0B1', '#00B25E'],
  73. gray: ['#fff', '#cfcfcf'],
  74. purple: ['#D3B5DF', '#8865A5'],
  75. }
  76. function getColorStop(key) {
  77. return {
  78. colorStops: [{
  79. offset: 0,
  80. color: colorStopList[key][0] // 0% 处的颜色
  81. }, {
  82. offset: 1,
  83. color: colorStopList[key][1] // 100% 处的颜色
  84. }]
  85. }
  86. }
  87. $scope.optionConfig = {
  88. getStaticMapOption: function (chartEntity, dataIn) {
  89. var data = dataIn.dataList;
  90. var mapName = 'china'
  91. var geoCoordMap = {};
  92. /*获取地图数据*/
  93. chartEntity.showLoading();
  94. var mapFeatures = echarts.getMap(mapName).geoJson.features;
  95. chartEntity.hideLoading();
  96. mapFeatures.forEach(function (v) {
  97. // 地区名称
  98. var name = v.properties.name;
  99. // 地区经纬度
  100. geoCoordMap[name] = v.properties.cp;
  101. });
  102. var tempSort = data.sort(function (a, b) {
  103. return b.value - a.value;
  104. })
  105. var tempSortLen = tempSort.length;
  106. // 值的范围
  107. var max, min;
  108. if (tempSortLen > 0) {
  109. // 值的范围
  110. max = tempSort[0].value
  111. min = tempSort[tempSortLen - 1].value;
  112. }
  113. // 地图气泡的大小范围
  114. var maxSize4Pin = 72,
  115. minSize4Pin = 30;
  116. var convertData = function (data) {
  117. var res = [];
  118. for (var i = 0; i < data.length; i++) {
  119. var geoCoord = geoCoordMap[data[i].name];
  120. if (geoCoord) {
  121. res.push({
  122. name: data[i].name,
  123. value: geoCoord.concat(data[i].value),
  124. });
  125. }
  126. }
  127. return res;
  128. };
  129. var markData = convertData(data);
  130. // 底点的最大尺寸
  131. var pointMaxSize = 25;
  132. var option = {
  133. visualMap: {
  134. show: false,
  135. min: 0,
  136. max: 500,
  137. left: 'left',
  138. top: 'bottom',
  139. text: ['高', '低'], // 文本,默认为数值文本
  140. calculable: true,
  141. seriesIndex: [1],
  142. inRange: {
  143. color: ['#044161', '#2B91B7']
  144. }
  145. },
  146. geo: {
  147. show: true,
  148. map: mapName,
  149. label: {
  150. normal: {
  151. show: false
  152. },
  153. emphasis: {
  154. show: false,
  155. }
  156. },
  157. roam: true,
  158. itemStyle: {
  159. normal: {
  160. areaColor: '#031525',
  161. borderColor: '#3B5077',
  162. },
  163. emphasis: {
  164. areaColor: '#2B91B7',
  165. }
  166. }
  167. },
  168. series: [{
  169. name: '散点',// 蓝色的小点
  170. type: 'scatter',
  171. coordinateSystem: 'geo',
  172. data: markData,
  173. symbolSize: function (val) {
  174. var size = val[2] / 10
  175. if (size > pointMaxSize) {
  176. size = pointMaxSize
  177. }
  178. return size;
  179. },
  180. label: {
  181. normal: {
  182. formatter: '{b}',
  183. position: 'right',
  184. show: true
  185. },
  186. emphasis: {
  187. show: true
  188. }
  189. },
  190. itemStyle: {
  191. normal: {
  192. color: '#05C3F9'
  193. }
  194. }
  195. }, {
  196. type: 'map',
  197. map: mapName,
  198. geoIndex: 0,
  199. aspectScale: 0.75, //长宽比
  200. showLegendSymbol: false, // 存在legend时显示
  201. label: {
  202. normal: {
  203. show: true
  204. },
  205. emphasis: {
  206. show: false,
  207. textStyle: {
  208. color: '#fff'
  209. }
  210. }
  211. },
  212. roam: true,
  213. itemStyle: {
  214. normal: {
  215. areaColor: '#031525',
  216. borderColor: '#3B5077',
  217. },
  218. emphasis: {
  219. areaColor: '#2B91B7'
  220. }
  221. },
  222. animation: false,
  223. data: data
  224. }, {
  225. // 小点上的气泡
  226. name: '气泡',
  227. type: 'scatter',
  228. coordinateSystem: 'geo',
  229. symbol: 'pin', //气泡
  230. symbolSize: function (val) {
  231. var a = val[2] / (max - min);//当前值和最大值的比例
  232. var size = minSize4Pin + (maxSize4Pin - minSize4Pin) * a;// 实际大小
  233. if (size > maxSize4Pin) {
  234. size = maxSize4Pin
  235. }
  236. return size;
  237. },
  238. label: {
  239. normal: {
  240. show: true,
  241. formatter: function (params) {
  242. var size = params.value[2]
  243. return size
  244. },
  245. textStyle: {
  246. color: '#fff',
  247. fontSize: 9,
  248. }
  249. }
  250. },
  251. itemStyle: {
  252. normal: {
  253. color: '#108EE9', //标志颜色
  254. }
  255. },
  256. zlevel: 6,
  257. data: markData,
  258. }, {
  259. // 排名前5 底部的小点变成黄色 漪涟
  260. name: 'Top 5',
  261. type: 'effectScatter',
  262. coordinateSystem: 'geo',
  263. data: convertData(data.sort(function (a, b) {
  264. return b.value - a.value;
  265. }).slice(0, 5)),
  266. symbolSize: function (val) {
  267. var size = val[2] / 10
  268. if (size > pointMaxSize) {
  269. size = pointMaxSize
  270. }
  271. return size;
  272. },
  273. showEffectOn: 'render',
  274. rippleEffect: {
  275. brushType: 'stroke'
  276. },
  277. hoverAnimation: true,
  278. label: {
  279. normal: {
  280. formatter: '{b}',
  281. position: 'right',
  282. show: true
  283. }
  284. },
  285. itemStyle: {
  286. normal: {
  287. color: 'yellow',
  288. shadowBlur: 10,
  289. shadowColor: 'yellow'
  290. }
  291. },
  292. zlevel: 1
  293. },
  294. ]
  295. };
  296. return option
  297. },
  298. //坐标系的公共风格
  299. getLineOptionsForMap: function (xData, textBreak) {
  300. var option = {
  301. tooltip: {
  302. trigger: 'axis',
  303. axisPointer: {
  304. lineStyle: {
  305. color: '#108EE9',
  306. width: .3,
  307. }
  308. }
  309. },
  310. grid: {
  311. x: 52,
  312. x2: 15,
  313. y: 30,
  314. y2: textBreak ? 32 : 28,// 自动换行的X坐标需要展示2行,空间要多一点
  315. },
  316. xAxis: [
  317. {
  318. type: 'category',
  319. axisLabel: {
  320. textStyle: {
  321. color: "#fff",
  322. fontSize: "12px"
  323. }
  324. },
  325. axisTick: {
  326. show: false,
  327. },
  328. axisLine: {
  329. show: false,
  330. },
  331. data: xData.map(function (str) {
  332. if (textBreak) {
  333. return autoBreak(str)
  334. } else {
  335. return str
  336. }
  337. })
  338. }
  339. ],
  340. yAxis: [
  341. {
  342. type: 'value',
  343. axisLabel: {
  344. textStyle: {
  345. color: "#fff",
  346. fontSize: "12px"
  347. }
  348. },
  349. axisTick: {
  350. show: false,
  351. },
  352. axisLine: {
  353. show: false,
  354. },
  355. splitLine: {
  356. show: false,
  357. },
  358. },
  359. ],
  360. series: []
  361. };
  362. return option;
  363. },
  364. getIncomeLineOption: function (data) {
  365. var payIncomeCount = 0;
  366. var lineCoinsCount = 0;
  367. var xData = [];
  368. var yData = {payIncome: [], lineCoins: []};
  369. for (var i = 0; i < data.length; i++) {
  370. var item = data[data.length - i - 1];
  371. xData.push(item.dateStr);
  372. yData.payIncome.push(item.payIncome);
  373. yData.lineCoins.push(item.lineCoins);
  374. payIncomeCount = payIncomeCount + item.payIncome;
  375. lineCoinsCount = lineCoinsCount + item.lineCoins;
  376. }
  377. var option = this.getLineOptionsForMap(xData);
  378. option.series = [
  379. {
  380. name: '在线收入',
  381. stack: '收入',
  382. type: 'bar',
  383. itemStyle: {
  384. color: "rgba(16,142,233,.9)",
  385. },
  386. data: yData.payIncome
  387. }, {
  388. name: '线下投币',
  389. stack: '收入',
  390. type: 'bar',
  391. itemStyle: {
  392. color: "rgba(16,142,233,.6)",
  393. },
  394. data: yData.lineCoins
  395. }
  396. ];
  397. return option;
  398. },
  399. // 由于早期的消费可能没有数据,需要给源数据,需要补齐 0,否则折现的时间轴和数据对应错误;
  400. fixConsumptionData: function (list) {
  401. // 找到所有key
  402. var allConsumKey = {};
  403. for (var index in list) {
  404. var item = list[index];
  405. var list2 = item.consumptionList;
  406. for (var index2 in list2) {
  407. var item2 = list2[index2];
  408. var name = item2.name;
  409. allConsumKey[name] = name;
  410. }
  411. }
  412. //修复该条数据。 这里只是多循环一次,性能问题不大。
  413. for (var index in list) {
  414. var item = list[index];
  415. if (!item.consumptionList) {
  416. item.consumptionList = []
  417. }
  418. var list2 = item.consumptionList;
  419. for (var key in allConsumKey) {
  420. var hasKeyFlag = false;
  421. for (var index2 in list2) {
  422. var item2 = list2[index2];
  423. var name = item2.name;
  424. // 如果有 key的消费数据,则找下一个key
  425. if (key === name) {
  426. hasKeyFlag = true;
  427. break;
  428. }
  429. }
  430. // 如果list2循环结束后,找不到key,则补全数据;
  431. if (!hasKeyFlag) {
  432. item.consumptionList.push({
  433. name: key,
  434. value: 0,
  435. });
  436. }
  437. }
  438. }
  439. },
  440. getConsumptionLineOption: function (list) {
  441. //补齐数据结构
  442. this.fixConsumptionData(list);
  443. var xData = [];
  444. var consumeSeriesMap = {};
  445. var length = list.length;
  446. for (var index in list) {
  447. // 正序时间排列
  448. var item = list[length - 1 - index];
  449. xData.push(item.dateStr);
  450. var list2 = item.consumptionList;
  451. for (var index2 in list2) {
  452. var item2 = list2[index2];
  453. var name = item2.name;
  454. var value = item2.value;
  455. if (!consumeSeriesMap[name]) {
  456. consumeSeriesMap[name] = [];
  457. }
  458. consumeSeriesMap[name].push(value);
  459. }
  460. }
  461. var myColor = this.getColorList();
  462. var option = this.getLineOptionsForMap(xData);
  463. var index = 0;
  464. for (var key in consumeSeriesMap) {
  465. var dataList = consumeSeriesMap[key];
  466. option.series.push({
  467. name: key,
  468. type: 'line',
  469. itemStyle: {
  470. normal: {
  471. color: myColor[index * 2],//相邻的颜色太相似了,所以间隔一个,越界不会异常,会使用默认色
  472. }
  473. },
  474. data: dataList
  475. });
  476. index++;
  477. }
  478. return option;
  479. },
  480. // pie的公共item风格
  481. getPieItemStyle: function () {
  482. var opt = {
  483. normal: {
  484. label: {
  485. show: true,
  486. position: 'outside',
  487. color: '#ddd',
  488. formatter: function (params) {
  489. return params.name + ':' + params.value;
  490. },
  491. rich: {
  492. white: {
  493. color: '#ddd',
  494. align: 'center',
  495. padding: [3, 0]
  496. }
  497. }
  498. },
  499. labelLine: {
  500. length: 8,
  501. length2: 12,
  502. show: true,
  503. }
  504. }
  505. };
  506. return opt
  507. },
  508. getUserPieOption: function (payload) {
  509. var option = {
  510. legend: {
  511. orient: 'vertical',
  512. align: 'left',
  513. x2: 10,
  514. y: 'center',
  515. textStyle: {
  516. color: "#ddd",
  517. fontSize: 12
  518. },
  519. data: ['总数', '日活', '男性', '女性', '未知',]
  520. },
  521. tooltip: {
  522. trigger: 'item',
  523. },
  524. series: [
  525. {
  526. type: 'pie',
  527. radius: ['0%', '28%'],
  528. center: ['40%', '50%'],
  529. label: {
  530. normal: {
  531. color: '#ddd',
  532. position: 'inner'
  533. }
  534. },
  535. labelLine: {
  536. normal: {
  537. show: false
  538. }
  539. },
  540. "itemStyle": {"normal": {borderWidth: 2}},
  541. data: [
  542. {
  543. value: payload.userCount,
  544. name: "总数",
  545. "itemStyle": {"normal": {"color": getColorStop("purple")}}
  546. },
  547. {
  548. value: payload.todayActiveUsers,
  549. name: "日活",
  550. "itemStyle": {"normal": {"color": getColorStop("green")}}
  551. }
  552. ]
  553. },
  554. {
  555. type: 'pie',
  556. radius: ['34%', '60%'],
  557. center: ['40%', '50%'],
  558. roseType: 'radius',
  559. itemStyle: this.getPieItemStyle(),
  560. data: [
  561. {
  562. value: payload.maleCount,
  563. name: "男性",
  564. "itemStyle": {"normal": {"color": getColorStop("blue"),}},
  565. },
  566. {
  567. value: payload.femaleCount,
  568. name: "女性",
  569. "itemStyle": {"normal": {"color": getColorStop("red"),}}
  570. },
  571. {
  572. value: (payload.userCount - payload.maleCount - payload.femaleCount),
  573. name: "未知",
  574. "itemStyle": {"normal": {"color": getColorStop("gray"),}}
  575. }]
  576. },
  577. ]
  578. };
  579. return option;
  580. },
  581. getFeedbackPieOption: function (payload) {
  582. var placeHolderStyle = {
  583. normal: {
  584. color: 'rgba(0,0,0,.1)',
  585. label: {
  586. show: false,
  587. },
  588. labelLine: {show: false}
  589. },
  590. emphasis: {
  591. color: 'rgba(0,0,0,0)',
  592. }
  593. };
  594. var seriesOpt = {
  595. type: 'pie',
  596. center: ['40%', '50%'],
  597. itemStyle: this.getPieItemStyle(),
  598. animationType: 'scale',
  599. animationEasing: 'elasticOut',
  600. animationDelay: function (idx) {
  601. return Math.random() * 200;
  602. }
  603. };
  604. var option = {
  605. legend: {
  606. orient: 'vertical',
  607. align: 'left',
  608. x2: 10,
  609. y: 'center',
  610. textStyle: {
  611. color: "#ddd",
  612. fontSize: 12
  613. },
  614. data: ['已上分', '已退币', '已维修',]
  615. },
  616. tooltip: {
  617. trigger: 'item',
  618. },
  619. series: [
  620. $.extend(true, {}, seriesOpt, {
  621. radius: ['28%', '38%'],
  622. data: [{
  623. value: payload.upperProcessedCount,
  624. name: '已上分',
  625. labelLine: {
  626. length: 20,
  627. length2: 20,
  628. show: true,
  629. },
  630. "itemStyle": {"normal": {"color": getColorStop("blue")}},
  631. }, {
  632. value: payload.upperCount - payload.upperProcessedCount,
  633. name: '未上分',
  634. label: {show: false},
  635. itemStyle: placeHolderStyle
  636. }],
  637. }),
  638. $.extend(true, {}, seriesOpt, {
  639. radius: ['40%', '50%'],
  640. data: [{
  641. value: payload.refundProcessedCount,
  642. name: '已退币',
  643. labelLine: {
  644. length: 10,
  645. length2: 20,
  646. show: true,
  647. },
  648. "itemStyle": {"normal": {"color": getColorStop("yellow")}},
  649. }, {
  650. value: payload.refundCount - payload.refundProcessedCount,
  651. name: '未退币',
  652. label: {show: false},
  653. itemStyle: placeHolderStyle
  654. }],
  655. }),
  656. $.extend(true, {}, seriesOpt, {
  657. radius: ['52%', '62%'],
  658. data: [{
  659. value: payload.faultProcessedCount,
  660. name: '已维修',
  661. "itemStyle": {"normal": {"color": getColorStop("red")}},
  662. }, {
  663. value: payload.faultCount - payload.faultProcessedCount,
  664. name: '未维修',
  665. label: {show: false},
  666. itemStyle: placeHolderStyle
  667. }],
  668. }),
  669. ]
  670. };
  671. return option;
  672. },
  673. getColorList: function () {
  674. var myColor = ['#f845f1', '#ad46f3', '#5045f6', '#4777f5', '#44aff0', '#45dbf7', '#f6d54a', '#f69846', '#ff4343'];
  675. return myColor;
  676. },
  677. // 由于早期的消费可能没有数据,需要给源数据,需要补齐 0,否则折现的时间轴和数据对应错误;
  678. fixData: function (list) {
  679. // 找到所有key
  680. var allConsumKey = {};
  681. for (var index in list) {
  682. var item = list[index];
  683. var list2 = item.items;
  684. for (var index2 in list2) {
  685. var item2 = list2[index2];
  686. var name = item2.name;
  687. allConsumKey[name] = name;
  688. }
  689. }
  690. //修复该条数据。 这里只是多循环一次,性能问题不大。
  691. for (var index in list) {
  692. var item = list[index];
  693. if (!item.items) {
  694. item.items = []
  695. }
  696. var list2 = item.items;
  697. for (var key in allConsumKey) {
  698. var hasKeyFlag = false;
  699. for (var index2 in list2) {
  700. var item2 = list2[index2];
  701. var name = item2.name;
  702. // 如果有 key的消费数据,则找下一个key
  703. if (key === name) {
  704. hasKeyFlag = true;
  705. break;
  706. }
  707. }
  708. // 如果list2循环结束后,找不到key,则补全数据;
  709. if (!hasKeyFlag) {
  710. item.items.push({
  711. name: key,
  712. value: 0,
  713. });
  714. }
  715. }
  716. }
  717. },
  718. // 设置公告的 pictorialBar风格
  719. setPictorialBarStyle: function (option, yData, hasPercent) {
  720. var myColor = this.getColorList();
  721. if (!hasPercent) {
  722. myColor.reverse();
  723. }
  724. option.tooltip.formatter = function (params) {
  725. var param = params[0];
  726. var name = param.name.replace(/[\n]/g, '');//去掉换行符号
  727. var span = '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + param.color + ';"></span>';
  728. if (hasPercent) {
  729. return span + name + ":占比" + param.value + "%"
  730. } else {
  731. return span + name + ":" + param.value
  732. }
  733. };
  734. option.series.push({
  735. name: '消费次数',
  736. type: 'pictorialBar',
  737. barCategoryGap: '20%',
  738. // 可以在线测试 symbol,http://www.runoob.com/try/try.php?filename=trysvg_path2
  739. // 稍尖:M200 200 c20 -10,80 -40, 85 -180c5 140,65 170,85 180l-170 0Z
  740. // 很尖:M200 200 c50 -10,80 -40, 85 -180c5 140,35 170,85 180l-170 0Z
  741. symbol: 'path://M200 200 c20 -10,80 -40, 85 -180c5 140,65 170,85 180l-170 0Z',
  742. label: {
  743. normal: {
  744. show: true,
  745. position: 'top',
  746. formatter: function (param) {
  747. if (hasPercent) {
  748. return param.value + "%"
  749. } else {
  750. return param.value
  751. }
  752. },
  753. textStyle: {
  754. fontSize: '12',
  755. color: '#fff'
  756. }
  757. }
  758. },
  759. itemStyle: {
  760. normal: {
  761. color: function (params) {
  762. var num = myColor.length;
  763. return myColor[params.dataIndex % num]
  764. },
  765. }
  766. },
  767. data: yData,
  768. });
  769. },
  770. getDealerIncomeTopChartOption: function (data) {
  771. var xData = [];
  772. var yData = [];
  773. for (var i = 0; i < data.length; i++) {
  774. var item = data[i];
  775. xData.push(item.name);
  776. yData.push(item.payIncomeTotal);
  777. }
  778. var option = this.getLineOptionsForMap(xData, true);
  779. this.setPictorialBarStyle(option, yData);
  780. return option
  781. },
  782. getUserConsumeFrequencyOption: function (data) {
  783. var xData = [];
  784. var yData = [];
  785. for (var i = 0; i < data.length; i++) {
  786. var item = data[i];
  787. xData.push(item.name);
  788. yData.push(item.percent);
  789. }
  790. var option = this.getLineOptionsForMap(xData);
  791. this.setPictorialBarStyle(option, yData, true);
  792. return option
  793. },
  794. // 全网用户
  795. getAllUserOption: function (list) {
  796. //补齐数据结构
  797. this.fixData(list);
  798. var xData = [];
  799. var consumeSeriesMap = {};
  800. var length = list.length;
  801. for (var index in list) {
  802. // 正序时间排列
  803. var item = list[length - 1 - index];
  804. xData.push(item.dateStr);
  805. var list2 = item.items;
  806. for (var index2 in list2) {
  807. var item2 = list2[index2];
  808. var name = item2.name;
  809. var value = item2.value;
  810. if (!consumeSeriesMap[name]) {
  811. consumeSeriesMap[name] = [];
  812. }
  813. consumeSeriesMap[name].push(value);
  814. }
  815. }
  816. var myColor = this.getColorList();
  817. var option = this.getLineOptionsForMap(xData);
  818. var index = 0;
  819. for (var key in consumeSeriesMap) {
  820. var dataList = consumeSeriesMap[key];
  821. option.series.push({
  822. name: key,
  823. type: 'line',
  824. itemStyle: {
  825. normal: {
  826. color: myColor[index * 2],//相邻的颜色太相似了,所以间隔一个,越界不会异常,会使用默认色
  827. }
  828. },
  829. data: dataList
  830. });
  831. index++;
  832. }
  833. return option;
  834. },
  835. getDevBeingUsedOption: function (data) {
  836. var xData = [];
  837. var yData = [];
  838. for (var i = 0; i < data.length; i++) {
  839. var item = data[i];
  840. xData.push(item.time);
  841. yData.push(item.devBeingUsed);
  842. }
  843. var option = this.getLineOptionsForMap(xData);
  844. option.series = [
  845. {
  846. name: '订单数',
  847. type: 'line',
  848. smooth: true,
  849. symbolSize: 0,
  850. itemStyle: {
  851. color: "rgba(16,142,233,.9)",
  852. },
  853. lineStyle: {
  854. normal: {
  855. width: 1
  856. }
  857. },
  858. areaStyle: { //区域填充样式
  859. normal: {
  860. //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
  861. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  862. {offset: 0, color: 'rgba(255,67,67, 0.8)'},
  863. {offset: 0.5, color: 'rgba(16,142,233, 0.5)'},
  864. {offset: 1, color: 'rgba(16,142,233, 0.1)'}
  865. ], false),
  866. shadowColor: 'rgba(53,142,215, 0.9)', //阴影颜色
  867. shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
  868. }
  869. },
  870. data: yData
  871. }
  872. ];
  873. return option;
  874. },
  875. };
  876. $scope.chartActive = {
  877. incomeChartLine: false,
  878. consumeChartLine: false,
  879. userChartPie: false,
  880. feedbackChartPie: false,
  881. dealerIncomeTopChart: false,
  882. userConsumeFrequencyChart: false,
  883. devBeingUsedChart: false,
  884. };
  885. var feature_map = $localStorage.feature_map
  886. //按条件加载统计图 因为有的接口太慢,避免等待,直接并发
  887. function loadChartData() {
  888. var url = '/manager/getDevMapChart'
  889. //获取数据:地图设备统计
  890. $http.get(url, {}).then(function (data) {
  891. var payload = data.data.payload
  892. if (payload) {
  893. //地图拓展api地址:https://github.com/ecomfe/echarts/tree/master/extension/bmap
  894. var option = $scope.optionConfig.getStaticMapOption(devChartPanelMap, payload);
  895. var userName = $('.app-header .navbar-right .hidden-sm').text();
  896. if (userName.indexOf('郑建如') > -1) {
  897. var date = new Date()
  898. var rand = date.getHours() * 55 + date.getMinutes() * 22 + date.getSeconds() * 3
  899. var rand2 = Math.round(Math.random() * 20);
  900. var v1 = 60172 + rand + rand2;
  901. var v2 = 92051 + rand + rand2;
  902. var v3 = 10297 - rand - rand2;
  903. // mock data
  904. $scope.showData.devBusy = v1;
  905. $scope.showData.devOnline = v2;
  906. $scope.showData.devOffline = v3;
  907. } else {
  908. $scope.showData.devBusy = payload.busy;
  909. $scope.showData.devOnline = payload.online;
  910. $scope.showData.devOffline = payload.offline;
  911. $scope.showData.unregistered = payload.unregistered;
  912. }
  913. devChartPanelMap.setOption(option);
  914. devChartPanelMap.resize();// 确保地图居中
  915. }
  916. }).then(function () {
  917. $scope.chartActive.incomeChartLine = true;
  918. var url = '/manager/getAllDeviceIncomeList'
  919. $http.get(url, {}).then(function (data) {
  920. data = data.data
  921. if (data.payload.dataList) {
  922. var option = $scope.optionConfig.getIncomeLineOption(data.payload.dataList);
  923. incomeChartLine.setOption(option);
  924. }
  925. });
  926. }).then(function () {
  927. $scope.chartActive.consumeChartLine = true;
  928. var url = '/manager/getAllDeviceConsumption'
  929. $http.get(url, {}).then(function (data) {
  930. data = data.data
  931. if (data.payload.dataList) {
  932. var option = $scope.optionConfig.getConsumptionLineOption(data.payload.dataList);
  933. consumeChartLine.setOption(option);
  934. }
  935. });
  936. }).then(function () {
  937. $scope.chartActive.userChartPie = true;
  938. var url = '/manager/getAllUserStatistics'
  939. $http.get(url, {}).then(function (data) {
  940. data = data.data
  941. if (data.payload) {
  942. var option = $scope.optionConfig.getUserPieOption(data.payload);
  943. userChartPie.setOption(option);
  944. }
  945. });
  946. }).then(function () {
  947. $scope.chartActive.feedbackChartPie = true;
  948. var url = '/manager/getAllFeedbackStatistics'
  949. $http.get(url, {}).then(function (data) {
  950. data = data.data
  951. if (data.payload) {
  952. var option = $scope.optionConfig.getFeedbackPieOption(data.payload);
  953. feedbackChartPie.setOption(option);
  954. }
  955. });
  956. }).then(function () {
  957. $scope.chartActive.dealerIncomeTopChart = true;
  958. var url = '/manager/getDealerIncomeTotalTop'
  959. $http.get(url, {}).then(function (data) {
  960. data = data.data
  961. if (data.payload) {
  962. var option = $scope.optionConfig.getDealerIncomeTopChartOption(data.payload.dataList);
  963. dealerIncomeTopChart.setOption(option);
  964. }
  965. });
  966. }).then(function () {
  967. $scope.chartActive.rightChart1 = true;
  968. var url = '/manager/getUserConsumeFrequency'
  969. $http.get(url, {}).then(function (data) {
  970. data = data.data
  971. if (data.payload) {
  972. var option = $scope.optionConfig.getUserConsumeFrequencyOption(data.payload.dataList);
  973. rightChart1.setOption(option);
  974. }
  975. });
  976. }).then(function () {
  977. $scope.chartActive.devBeingUsedChart = true;
  978. var url = '/manager/getDevBeingUsedTrend'
  979. $http.get(url, {}).then(function (data) {
  980. data = data.data
  981. if (data.payload) {
  982. var option = $scope.optionConfig.getDevBeingUsedOption(data.payload.dataList);
  983. devBeingUsedChart.setOption(option);
  984. }
  985. });
  986. })
  987. }
  988. $scope.chartHasLoad = false
  989. $scope.loadAllChart = function () {
  990. loadChartData();
  991. $scope.chartHasLoad = true
  992. }
  993. // 全屏事件绑定
  994. $scope.isFullscreen = false;
  995. $scope.$on('fullscreenchange', function (evt, data) {
  996. $timeout(function () {
  997. $scope.isFullscreen = screenfull.isFullscreen;
  998. resizeChart()
  999. })
  1000. });
  1001. }]);