HybridCharts.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <!-- 饼图统计 -->
  2. <template>
  3. <div class="box">
  4. <boxTop :title="title"/>
  5. <div class="cakeBox">
  6. <div class="flex">
  7. <div class="chartsDom" id="PieCharts"></div>
  8. <div class="panel">
  9. <div class="panel-item" v-for="item in chartData">
  10. <div class="color" :style="{'background-color':item.color }"></div>
  11. <div class="type">{{ item.name }}</div>
  12. <div class="number">{{ item.value }}%</div>
  13. <div class="amount">¥{{ item.amount }}</div>
  14. </div>
  15. </div>
  16. </div>
  17. </div>
  18. <div id="rankingCharts"></div>
  19. </div>
  20. </template>
  21. <script>
  22. import boxTop from '@/components/boxTop/index.vue'
  23. export default {
  24. data() {
  25. return {
  26. isHoist: true,
  27. tabs: {
  28. index: this.$props.tabIndex,
  29. list: [`交易额`, `交易类型`],
  30. },
  31. chartData: [
  32. {
  33. value: 30,
  34. name: "平台一",
  35. color: '#975fe4',
  36. amount: 3395,
  37. },
  38. {
  39. value: 40,
  40. name: "平台二",
  41. color: '#45a5ff',
  42. amount: 2323
  43. },
  44. {
  45. value: 50,
  46. name: "平台三",
  47. color: '#81c926',
  48. amount: 3322
  49. },
  50. {
  51. value: 20,
  52. name: "平台四",
  53. amount: 6644,
  54. color: '#ff8e49'
  55. },
  56. {
  57. value: 16,
  58. name: "平台五",
  59. amount: 3211,
  60. color: '#37cbcb'
  61. },
  62. ]
  63. }
  64. },
  65. components: {
  66. boxTop,
  67. },
  68. props: {
  69. id: {
  70. type: String,
  71. default: ``,
  72. },
  73. data: {
  74. type: Object,
  75. default: new Object(),
  76. },
  77. tabIndex: {
  78. type: Number,
  79. default: 0,
  80. },
  81. title: {
  82. type: String,
  83. default: ``,
  84. },
  85. titleEn: {
  86. type: String,
  87. default: `Tongren Tobacco Planting Digital Management Platform`,
  88. },
  89. },
  90. async mounted() {
  91. this.getEchart()
  92. this.getEchartAgain()
  93. },
  94. watch: {
  95. data: {
  96. handler() {
  97. this.getEchart()
  98. this.getEchartAgain()
  99. },
  100. deep: true, // 深度监听
  101. immediate: true, // 立即执行
  102. },
  103. },
  104. methods: {
  105. getEchart() {
  106. let myChart = echarts.init(document.getElementById('PieCharts'))
  107. const sum = this.chartData.reduce((per, cur) => per + cur.value, 0);
  108. const gap = (1 * sum) / 100;
  109. const pieData1 = [];
  110. const gapData = {
  111. name: "",
  112. value: gap,
  113. itemStyle: {
  114. color: "transparent",
  115. },
  116. };
  117. const color = this.chartData.map(item => item.color);
  118. for (let i = 0; i < this.chartData.length; i++) {
  119. // 第一圈数据
  120. pieData1.push({
  121. ...this.chartData[i],
  122. });
  123. pieData1.push(gapData);
  124. }
  125. let option = {
  126. color,
  127. title: {
  128. show: true,
  129. text: sum.toLocaleString(),
  130. subtext: "订单总量",
  131. x: "45%",
  132. y: "35%",
  133. itemGap: 6,
  134. textStyle: {
  135. color: "hsla(179, 100%, 65%, 1)",
  136. fontSize: 24,
  137. fontWeight: "400"
  138. },
  139. subtextStyle: {
  140. color: "#fff",
  141. fontSize: 12,
  142. fontWeight: "400"
  143. },
  144. textAlign: "center",
  145. },
  146. series: [
  147. {
  148. name: "",
  149. type: "pie",
  150. roundCap: true,
  151. radius: ["82%", "92%"],
  152. center: ["50%", "50%"],
  153. data: pieData1,
  154. labelLine: {
  155. length: 8,
  156. length2: 16,
  157. lineStyle: {
  158. width: 1,
  159. },
  160. },
  161. label: {
  162. show: false,
  163. },
  164. },
  165. {
  166. type: "pie",
  167. radius: ["78%", "81%"],
  168. center: ["50%", "50%"],
  169. animation: false,
  170. hoverAnimation: false,
  171. data: [
  172. {
  173. value: 100,
  174. },
  175. ],
  176. label: {
  177. show: false,
  178. },
  179. itemStyle: {
  180. normal: {
  181. color: "#3BC5EF",
  182. },
  183. },
  184. },
  185. {
  186. name: "",
  187. type: "pie",
  188. startAngle: 90,
  189. radius: "77%",
  190. animation: false,
  191. hoverAnimation: false,
  192. center: ["50%", "50%"],
  193. itemStyle: {
  194. normal: {
  195. labelLine: {
  196. show: false,
  197. },
  198. color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
  199. {
  200. offset: 1,
  201. color: "rgba(50,171,241, 0)",
  202. },
  203. {
  204. offset: 0.5,
  205. color: "rgba(50,171,241, .4)",
  206. },
  207. {
  208. offset: 0,
  209. color: "rgba(55,70,130, 0)",
  210. },
  211. ]),
  212. shadowBlur: 60,
  213. },
  214. },
  215. data: [
  216. {
  217. value: 100,
  218. },
  219. ],
  220. },
  221. ],
  222. };
  223. myChart.setOption(option)
  224. },
  225. getEchartAgain() {
  226. let myChart = echarts.init(document.getElementById('rankingCharts'))
  227. const dataSource = [
  228. {name: '服务数据管理', value: 3713, percent: "29.5"},
  229. {name: '组织部', value: 3022, percent: "32"},
  230. {name: '服务数据', value: 2647, percent: "24.3"},
  231. {name: '水务管理', value: 2291, percent: "50"},
  232. {name: '水务管理', value: 2291, percent: "50"}
  233. ];
  234. let dataSourcemax = 0
  235. dataSource.forEach((item) => {
  236. if (dataSourcemax < item.value) {
  237. dataSourcemax = item.value
  238. }
  239. })
  240. const salvProMax = dataSource.map(item => dataSourcemax)
  241. const title = '责任单位指标总数'
  242. let option = {
  243. title: [
  244. {
  245. show: false,
  246. text: title,
  247. fontSize: 20,
  248. color: '#fff',
  249. fontWeight: 600,
  250. x: '70%',
  251. y: '3%',
  252. },
  253. ],
  254. grid: {
  255. left: '6%',
  256. right: '6%',
  257. top: '10%',
  258. bottom: '8%',
  259. },
  260. xAxis: {
  261. show: false,
  262. type: 'value',
  263. max: dataSourcemax + 100
  264. },
  265. yAxis: [
  266. {
  267. type: 'category',
  268. inverse: true,
  269. axisLine: {
  270. show: false
  271. },
  272. axisTick: {
  273. show: false
  274. },
  275. axisLabel: {
  276. color: '#fff',
  277. align: 'left',
  278. verticalAlign: 'bottom',
  279. position: 'right',
  280. padding: [0, 0, 5, 15],
  281. fontSize: 12,
  282. },
  283. data: dataSource.map(item => item.name)
  284. }
  285. ],
  286. tooltip: {
  287. trigger: 'item'
  288. },
  289. series: [
  290. {
  291. type: 'bar',
  292. barWidth: 10,
  293. itemStyle: {
  294. padding: [0, 0, 0, 0],
  295. normal: {
  296. color: new echarts.graphic.LinearGradient(0, 0, 1, 0,
  297. [{
  298. offset: 0,
  299. color: 'rgba(77, 255, 251, 0.3)'
  300. },
  301. {
  302. offset: 1,
  303. color: 'rgba(77, 255, 251, 1)'
  304. }
  305. ], false),
  306. }
  307. },
  308. label: {
  309. show: false,
  310. offset: [10, -20],
  311. formatter: '{c}人',
  312. position: 'insideRight', // 在上方显示
  313. // position: 'insideLeft',
  314. // 数值样式,显示的文字大小和颜色
  315. fontSize: '12',
  316. color: '#f00',
  317. fontWeight: 400,
  318. lineHeight: '18'
  319. },
  320. data: dataSource
  321. },
  322. {
  323. z: 1,
  324. name: '背景',
  325. type: 'bar',
  326. barWidth: 8,
  327. barGap: '-100%',
  328. data: salvProMax,
  329. itemStyle: {
  330. color: 'rgba(0, 255, 255, 0.3)',
  331. // borderRadius: [30, 30, 30, 30]
  332. },
  333. tooltip: {show: false},
  334. label: {
  335. show: true, // 开启显示
  336. offset: [10, -20],
  337. formatter: function (fItem) {
  338. let obj = dataSource.find(item => item.name === fItem.name)
  339. return `{unitWid|交易量}{value|${obj.value}}{unit|交易额}{percent|${obj.percent}}`
  340. },
  341. position: 'insideRight', // 在上方显示
  342. // 数值样式,显示的文字大小和颜色
  343. fontSize: '14',
  344. fontWeight: 400,
  345. lineHeight: '18',
  346. rich: {
  347. value: {
  348. color: '#00ffff',
  349. fontSize: 16,
  350. padding: [0, 0, -10, 5]
  351. },
  352. percent: {
  353. color: '#00ffff',
  354. fontSize: 16,
  355. padding: [0, 0, -10, 5],
  356. align: 'right',
  357. },
  358. unitWid: {
  359. fontSize: 12,
  360. color: 'rgba(255, 255, 255, 0.7)',
  361. padding: [0, 0, -10, 40],
  362. // width: 80,
  363. },
  364. unit: {
  365. fontSize: 12,
  366. color: 'rgba(255, 255, 255, 0.7)',
  367. padding: [0, 0, -10, 40]
  368. }
  369. }
  370. },
  371. }
  372. ]
  373. };
  374. myChart.setOption(option)
  375. }
  376. },
  377. }
  378. </script>
  379. <style lang="less" scoped>
  380. .box {
  381. width: 460px;
  382. height: 428px;
  383. background: linear-gradient(rgba(0, 32, 77, 0.8) 0%, rgba(0, 32, 77, 0.5) 100%);
  384. box-shadow: inset 0px 0px 20px 0px rgba(27, 146, 255, 0.3);
  385. }
  386. #rankingCharts {
  387. width: 460px;
  388. height: 210px;
  389. }
  390. .cakeBox {
  391. width: 460px;
  392. height: 160px;
  393. .chartsDom {
  394. margin: 8px 30px;
  395. width: 150px;
  396. height: 150px;
  397. }
  398. }
  399. .flex {
  400. display: flex;
  401. align-items: center;
  402. }
  403. .l-height {
  404. line-height: 100%;
  405. }
  406. .space_around {
  407. justify-content: space-around;
  408. align-items: center;
  409. }
  410. .space_between {
  411. justify-content: space-between;
  412. align-items: center;
  413. }
  414. .number {
  415. text-align: center;
  416. font-size: 16px;
  417. padding: 4px 0;
  418. margin: 3px 0;
  419. }
  420. .text {
  421. font-size: 14px;
  422. color: #888888;
  423. display: flex;
  424. justify-content: center;
  425. align-items: center;
  426. }
  427. .column_reverse {
  428. flex-direction: column-reverse;
  429. }
  430. .panel {
  431. height: 114px;
  432. box-sizing: border-box;
  433. display: flex;
  434. justify-content: space-around;
  435. flex-direction: column;
  436. .panel-item {
  437. display: flex;
  438. align-items: center;
  439. justify-content: space-around;
  440. height: 20px;
  441. width: 195px;
  442. font-size: 12px;
  443. .color {
  444. border-radius: 2px;
  445. width: 10px;
  446. height: 10px;
  447. }
  448. }
  449. }
  450. .title {
  451. display: flex;
  452. align-items: center;
  453. margin: 10px 30px;
  454. .label {
  455. font-weight: 600;
  456. font-size: 16px;
  457. color: #FFFFFF;
  458. }
  459. .value {
  460. font-weight: bold;
  461. font-size: 24px;
  462. background: linear-gradient(0deg, rgba(27, 146, 255, 1) 0%, rgba(255, 255, 255, 1) 50%);
  463. background-clip: text;
  464. -webkit-background-clip: text;
  465. -webkit-text-fill-color: transparent;
  466. }
  467. }
  468. .title > * {
  469. margin: 0 6px;
  470. }
  471. .AICenter {
  472. display: flex;
  473. align-items: center
  474. }
  475. </style>