chartFunnel.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <template>
  2. <home-section
  3. :title="title"
  4. :options="dropOptions"
  5. @status="handleToggleStatus">
  6. <view class="chart-body">
  7. <view class="chart-core">
  8. <!--#ifdef MP-ALIPAY -->
  9. <canvas
  10. id="funnelChart"
  11. canvas-id="funnelChart"
  12. class="charts"
  13. :width="cWidth*pixelRatio"
  14. :height="cHeight*pixelRatio"
  15. :style="{'width':cWidth+'px','height':cHeight+'px'}"
  16. @touchstart="touchPie($event, 'funnelChart')" />
  17. <!--#endif-->
  18. <!--#ifndef MP-ALIPAY -->
  19. <canvas
  20. id="funnelChart"
  21. canvas-id="funnelChart"
  22. class="charts"
  23. @touchstart="touchPie($event, 'funnelChart')" />
  24. <!--#endif-->
  25. </view>
  26. <view class="info-box">
  27. <view class="box" style="color: #6ca2ff">
  28. <text class="mini-title">
  29. 赢单
  30. </text>
  31. <text class="info">
  32. {{ funnelData.winSingle || '0.00' }}元
  33. </text>
  34. </view>
  35. <view class="box" style="color: #ff7474">
  36. <text class="mini-title">
  37. 输单
  38. </text>
  39. <text class="info">
  40. {{ funnelData.loseSingle || '0.00' }}元
  41. </text>
  42. </view>
  43. </view>
  44. </view>
  45. </home-section>
  46. </template>
  47. <script>
  48. import { crmInstrumentSellFunnel } from 'API/crm/work'
  49. import { BusinessStatusOptions } from 'API/crm/business'
  50. import HomeSection from './homeSection'
  51. import uCharts from '@/components/u-charts/u-charts.js'
  52. let funnelChart = null
  53. // 销售漏斗
  54. export default {
  55. name: 'ChartFunnel',
  56. components: {
  57. HomeSection
  58. },
  59. props: {
  60. params: {
  61. type: Object,
  62. default: () => {}
  63. }
  64. },
  65. data() {
  66. return {
  67. loading: false,
  68. title: '销售漏斗',
  69. dropOptions: [],
  70. cWidth: '',
  71. cHeight: '',
  72. pixelRatio: 1,
  73. serverData: '',
  74. funnelData: {}
  75. }
  76. },
  77. watch: {
  78. params: {
  79. handler() {
  80. if (this.dropVal) {
  81. this.getData(this.dropVal)
  82. }
  83. },
  84. deep: true
  85. }
  86. },
  87. mounted() {
  88. const _self = this;
  89. // #ifdef MP-ALIPAY
  90. uni.getSystemInfo({
  91. success: function(res) {
  92. if (res.pixelRatio > 1) {
  93. // 正常这里给2就行,如果pixelRatio=3性能会降低一点
  94. // _self.pixelRatio =res.pixelRatio;
  95. _self.pixelRatio = 2;
  96. }
  97. }
  98. });
  99. // #endif
  100. this.cWidth = uni.upx2px(686);
  101. this.cHeight = uni.upx2px(380);
  102. this.gaugeWidth = uni.upx2px(30);
  103. this.getBusinessOptions();
  104. },
  105. methods: {
  106. getData(typeId) {
  107. if (this.loading) return
  108. this.loading = true
  109. this.dropVal = typeId
  110. crmInstrumentSellFunnel({
  111. ...this.params,
  112. typeId: typeId
  113. }).then(res => {
  114. this.loading = false
  115. console.log('销售漏斗:', res)
  116. this.funnelData = {
  117. winSingle: res.sumYing,
  118. loseSingle: res.sumShu
  119. }
  120. this.initChart('funnelChart', res.list || [])
  121. }).catch(() => {
  122. this.loading = false
  123. })
  124. },
  125. getBusinessOptions() {
  126. if (this.loading) return
  127. this.loading = true
  128. BusinessStatusOptions().then(res => {
  129. this.loading = false
  130. this.dropOptions = res.map(item => {
  131. return {
  132. label: item.name,
  133. value: item.typeId
  134. }
  135. })
  136. }).catch(() => {
  137. this.loading = false
  138. })
  139. },
  140. handleToggleStatus(typeId) {
  141. this.getData(typeId)
  142. },
  143. initChart(canvasId, chartData) {
  144. const _self = this
  145. const seriesData = chartData.map((o, i) => {
  146. return {
  147. name: o.name,
  148. data: o.count,
  149. money: o.money
  150. }
  151. })
  152. // eslint-disable-next-line new-cap
  153. funnelChart = new uCharts({
  154. $this: _self,
  155. canvasId: canvasId,
  156. width: _self.cWidth * _self.pixelRatio,
  157. height: _self.cHeight * _self.pixelRatio,
  158. type: 'funnel',
  159. pixelRatio: _self.pixelRatio,
  160. background: '#FFFFFF',
  161. fontSize: 12,
  162. animation: false,
  163. dataLabel: true,
  164. // legend: { // 图例
  165. // show: false
  166. // },
  167. extra: {
  168. funnel: {
  169. border: true,
  170. activeWidth: 5,
  171. borderWidth: 2,
  172. borderColor: '#FFFFFF'
  173. },
  174. tooltip: {}
  175. },
  176. series: seriesData
  177. })
  178. console.log('funnelChart', funnelChart)
  179. },
  180. touchPie(e) {
  181. funnelChart.showToolTip(e, {
  182. textList: [
  183. { text: '' },
  184. { text: '' }
  185. ],
  186. format: function(item, category) {
  187. console.log('item', item)
  188. console.log('category', category)
  189. this.textList = [
  190. { text: `${item.name}(${item.data})`, color: item.color },
  191. { text: `预测金额:${item.money}元`, color: null }
  192. ]
  193. return this.textList
  194. }
  195. })
  196. }
  197. }
  198. }
  199. </script>
  200. <style scoped lang="scss">
  201. .chart-body {
  202. padding: 20rpx 0;
  203. .charts {
  204. position: relative;
  205. width: 100%;
  206. height: 380rpx;
  207. }
  208. .info-box {
  209. width: 100%;
  210. @include center;
  211. .box {
  212. width: 40%;
  213. flex-direction: column;
  214. @include center;
  215. .mini-title {
  216. font-size: 24rpx;
  217. }
  218. .info {
  219. font-size: 28rpx;
  220. }
  221. }
  222. }
  223. }
  224. </style>