index.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <template>
  2. <Card :title="title" :icon="icon" class="resident">
  3. <div class="display-flex w-full">
  4. <div class="gauge margin-r-30">
  5. <div ref="dom" class="hfw-gauge"></div>
  6. </div>
  7. <div class="num display-flex flex-1">
  8. <div v-for="item in residentData" :key="item.title" class="resident-item flex-1">
  9. <div class="title">{{ item.title }}</div>
  10. <div class="value">{{ item.value | formatNumber }}</div>
  11. </div>
  12. </div>
  13. </div>
  14. <div class="operate display-flex w-full" v-if="showOperate">
  15. <div v-for="item in operateData" :key="item.title" class="operate-item flex-1">
  16. <div class="icon margin-t-30">
  17. <img :src="item.icon" alt="" class="img">
  18. </div>
  19. <div class="title">{{ item.title }}</div>
  20. <div class="value">{{ item.value | formatNumber }}</div>
  21. </div>
  22. </div>
  23. </Card>
  24. </template>
  25. <script>
  26. import * as echarts from 'echarts'
  27. import Card from '@/views/hui-jia/components/card'
  28. import icon from './images/icon-title.png'
  29. import iconReport from './images/icon-report.png'
  30. import iconQrcode from './images/icon-qrcode.png'
  31. import iconPay from './images/icon-pay.png'
  32. import { huiJiaApi } from '@/api'
  33. export default {
  34. name: 'Resident',
  35. components: {
  36. Card
  37. },
  38. props: {
  39. showOperate: {
  40. type: Boolean,
  41. default: true
  42. }
  43. },
  44. data () {
  45. return {
  46. rate: 0,
  47. title: '用户信息',
  48. icon: icon,
  49. residentData: [
  50. {
  51. title: '公众号关注数',
  52. value: 1000,
  53. key: 'mpFollowCount'
  54. },
  55. {
  56. title: '绘服务绑定数',
  57. value: 1000,
  58. key: 'hfwBindCount'
  59. },
  60. {
  61. title: '日活跃数(近1月)',
  62. value: 1000,
  63. key: 'userLiveCount'
  64. }
  65. ],
  66. operateData: [
  67. {
  68. title: '绘服务缴费次数',
  69. value: 1000,
  70. icon: iconPay,
  71. key: 'payCount'
  72. },
  73. {
  74. title: '绘服务扫码次数',
  75. value: 1000,
  76. icon: iconQrcode,
  77. key: 'scanCodeCount'
  78. },
  79. {
  80. title: '绘服务报事次数',
  81. value: 1000,
  82. icon: iconReport,
  83. key: 'workCount'
  84. }
  85. ],
  86. colorArr: ['#182744', '#82D1F6', '#02338C']
  87. }
  88. },
  89. mounted () {
  90. this.getUsersStatistics()
  91. },
  92. methods: {
  93. getUsersStatistics () {
  94. huiJiaApi.getUsersStatistics().then(res => {
  95. if(res && res.data){
  96. this.rate = res.data.data.attentionRate || 0
  97. this.residentData.forEach(item => {
  98. item.value = res.data.data[item.key] || 0
  99. })
  100. this.operateData.forEach(item => {
  101. item.value = res.data.data[item.key] || 0
  102. })
  103. this.initChart()
  104. }
  105. })
  106. },
  107. initChart () {
  108. const myChart = echarts.init(this.$refs.dom)
  109. const option = {
  110. title: {
  111. show: true,
  112. text: [`{titleBg|关注率}`],
  113. left: 'center',
  114. bottom: '0',
  115. textStyle: {
  116. rich: {
  117. titleBg: {
  118. backgroundColor: '#14223C',
  119. borderRadius: 4,
  120. height: 26,
  121. width: 70,
  122. color: '#00CAFF',
  123. fontSize: 14
  124. }
  125. }
  126. }
  127. },
  128. angleAxis: {
  129. show: false,
  130. max: 100 * 360 / 270, // -45度到225度,二者偏移值是270度除360度
  131. type: 'value',
  132. startAngle: 225, // 极坐标初始角度
  133. splitLine: {
  134. show: false
  135. }
  136. },
  137. barMaxWidth: 16, // 圆环宽度
  138. radiusAxis: {
  139. show: false,
  140. type: 'category'
  141. },
  142. // 圆环位置和大小
  143. polar: {
  144. center: ['50%', '50%'],
  145. radius: '170%'
  146. },
  147. series: [{
  148. type: 'bar',
  149. data: [{ // 上层圆环,显示数据
  150. value: 75,
  151. itemStyle: {
  152. color: { // 图形渐变颜色方法,四个数字分别代表,右,下,左,上,offset表示0%到100%
  153. type: 'linear',
  154. x: 0,
  155. y: 0,
  156. x2: 1, // 从左到右 0-1
  157. y2: 0,
  158. colorStops: [{
  159. offset: 0,
  160. color: this.colorArr[1]
  161. }, {
  162. offset: 1,
  163. color: this.colorArr[2]
  164. }]
  165. }
  166. }
  167. }],
  168. // barGap: '-100%', // 柱间距离,上下两层圆环重合
  169. coordinateSystem: 'polar',
  170. roundCap: true // 顶端圆角从 v4.5.0 开始支持
  171. // z: 2 // 圆环层级,同zindex
  172. },
  173. { // 下层圆环,显示最大值
  174. type: 'bar',
  175. data: [{
  176. value: 100,
  177. itemStyle: {
  178. color: this.colorArr[0]
  179. }
  180. }],
  181. barGap: '-100%',
  182. coordinateSystem: 'polar',
  183. roundCap: true,
  184. z: 1
  185. },
  186. // 仪表盘
  187. {
  188. name: '关注率',
  189. type: 'gauge',
  190. axisLine: {
  191. show: false
  192. },
  193. splitLine: {
  194. show: false
  195. },
  196. axisTick: {
  197. show: false
  198. },
  199. axisLabel: {
  200. show: false
  201. },
  202. splitLabel: {
  203. show: false
  204. },
  205. pointer: {
  206. show: false
  207. },
  208. title: {
  209. offsetCenter: [0, '45%'],
  210. fontSize: 14,
  211. fontFamily: 'Microsoft YaHei',
  212. fontWeight: '400',
  213. color: '#5774A2'
  214. },
  215. detail: {
  216. formatter: '{value}%',
  217. offsetCenter: [0, '-10%'],
  218. fontSize: 22,
  219. fontFamily: 'DS-Digital',
  220. fontWeight: 'bold',
  221. color: '#00D2ED'
  222. },
  223. data: [{
  224. value: this.rate,
  225. name: '绘服务'
  226. }]
  227. }
  228. ]
  229. }
  230. myChart.setOption(option)
  231. myChart.resize()
  232. }
  233. }
  234. }
  235. </script>
  236. <style lang="scss">
  237. @import '@/assets/css/function.scss';
  238. @import '@/assets/css/screen.scss';
  239. .resident{
  240. .gauge{
  241. width: 50%;
  242. .hfw-gauge{
  243. width: halfW(220);
  244. height: halfH(220);
  245. margin: 0 auto;
  246. }
  247. }
  248. .num{
  249. flex-direction: column;
  250. text-align: center;
  251. gap: halfH(20);
  252. .resident-item{
  253. align-content: center;
  254. }
  255. .title{
  256. font-size: halfW(16);
  257. color: #82D1F6;
  258. }
  259. .value{
  260. font-size: halfW(20);
  261. color: #FFFFFF;
  262. margin-top: halfH(10);
  263. }
  264. }
  265. .operate{
  266. width: 100%;
  267. height: calc(45%);
  268. text-align: center;
  269. border-radius: 5px;
  270. background-color: rgba(17, 28, 48, 1);
  271. border: 1px solid rgba(0, 123, 211, 0.2);
  272. align-items: center;
  273. .operate-item{
  274. border-right: 1px solid rgba(0, 123, 211, 0.2);
  275. }
  276. .operate-item:last-child{
  277. border-right: none;
  278. }
  279. .img{
  280. width: halfW(40);
  281. height: halfW(40);
  282. }
  283. .title{
  284. font-size: halfW(20);
  285. color: #82D1F6;
  286. margin: halfH(20) 0;
  287. }
  288. .value{
  289. font-size: halfW(20);
  290. color: #FFFFFF;
  291. }
  292. }
  293. }
  294. </style>