dataTendency.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <div v-loading="loading">
  3. <MetricsCards v-model="metrics" :metric-items="metricsItems" @change="changeMetric"></MetricsCards>
  4. <div style="height: 350px;" ref="chartRef"></div>
  5. </div>
  6. </template>
  7. <script lang="ts" setup>
  8. import {ref, onMounted, onBeforeUnmount, Ref, onBeforeMount, watch, computed} from 'vue'
  9. import * as echarts from 'echarts'
  10. import {useShopInfo} from '/@/stores/shopInfo'
  11. import {getLineData, getCardData} from '../api'
  12. import {spCampaignMetricsEnum} from '/@/views/adManage/utils/enum.js'
  13. import MetricsCards from '/@/components/MetricsCards/index.vue'
  14. import XEUtils from 'xe-utils'
  15. import {buildChartOpt} from '/@/views/adManage/utils/tools.js'
  16. import {usePublicData} from '/@/stores/publicData'
  17. import {storeToRefs} from 'pinia'
  18. defineOptions({
  19. name: 'DataTendencyChart'
  20. })
  21. onMounted(() => {
  22. getMetricsItems()
  23. addResize()
  24. // initLine()
  25. setTimeout(() => {
  26. initLine()
  27. }, 0)
  28. })
  29. onBeforeUnmount(() => {
  30. if (chartObj) {
  31. chartObj.dispose()
  32. chartObj = null
  33. }
  34. removeResize()
  35. })
  36. const publicData = usePublicData()
  37. const metrics = ref([
  38. {metric: 'Impression', color: '#0085ff', 'label': '曝光量'},
  39. {metric: 'Click', color: '#3fd4cf', 'label': '点击量'},
  40. {metric: 'Spend', color: '#ff9500', 'label': '花费'},
  41. ])
  42. const shopInfo = useShopInfo()
  43. const metricsItems: Ref<MetricData[]> = ref([])
  44. let chartObj: any
  45. const chartRef = ref()
  46. const option: any = {
  47. dataset: {
  48. source: []
  49. },
  50. tooltip: {
  51. trigger: 'axis',
  52. axisPointer: {
  53. label: {
  54. backgroundColor: '#6a7985'
  55. }
  56. }
  57. },
  58. legend: {
  59. selected: {}, // 控制显隐
  60. show: false
  61. },
  62. grid: {
  63. top: 50, right: 150, bottom: 30, left: 55,
  64. },
  65. xAxis: {
  66. type: 'category'
  67. },
  68. yAxis: [
  69. {
  70. id: 0,
  71. type: 'value',
  72. name: '曝光量',
  73. splitLine: {
  74. show: true // 设置显示分割线
  75. },
  76. axisLine: {
  77. show: true,
  78. lineStyle: {
  79. color: '#0085ff'
  80. }
  81. },
  82. show: true
  83. },
  84. {
  85. id: 1,
  86. type: 'value',
  87. name: '点击量',
  88. position: 'right',
  89. splitLine: {
  90. show: false
  91. },
  92. axisLine: {
  93. show: true,
  94. lineStyle: {
  95. color: '#3fd4cf'
  96. }
  97. },
  98. show: true
  99. },
  100. {
  101. id: 2,
  102. type: 'value',
  103. position: 'right',
  104. offset: 90,
  105. name: '花费',
  106. splitLine: {
  107. show: false
  108. },
  109. axisLine: {
  110. show: true,
  111. lineStyle: {
  112. color: '#ff9500'
  113. }
  114. },
  115. show: true
  116. }
  117. ],
  118. series: [
  119. {
  120. id: 0,
  121. name: '曝光量',
  122. type: 'bar',
  123. encode: {
  124. x: 'date',
  125. y: 'Impression'
  126. },
  127. barWidth: '20px',
  128. yAxisIndex: 0,
  129. itemStyle: {
  130. color: '#0085ff',
  131. borderRadius: [6, 6, 6, 6],
  132. }
  133. },
  134. {
  135. id: 1,
  136. name: '点击量',
  137. type: 'line',
  138. encode: {
  139. x: 'date',
  140. y: 'Click'
  141. },
  142. symbolSize: 6,
  143. symbol: 'circle',
  144. smooth: true,
  145. yAxisIndex: 1,
  146. itemStyle: {color: '#3fd4cf', borderColor: '#3fd4cf'},
  147. areaStyle: {
  148. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  149. {offset: 0, color: '#3fd4cf53'},
  150. {offset: 1, color: '#3fd4cf03'},
  151. ]),
  152. },
  153. emphasis: {
  154. focus: 'series'
  155. }
  156. },
  157. {
  158. id: 2,
  159. name: '花费',
  160. type: 'line',
  161. encode: {
  162. x: 'date',
  163. y: 'Spend'
  164. },
  165. symbolSize: 6,
  166. symbol: 'circle',
  167. smooth: true,
  168. yAxisIndex: 2,
  169. itemStyle: {color: '#ff9500', borderColor: '#ff9500'},
  170. areaStyle: {
  171. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  172. {offset: 0, color: '#ff950053'},
  173. {offset: 1, color: '#ff950003'},
  174. ]),
  175. },
  176. emphasis: {
  177. focus: 'series'
  178. }
  179. }
  180. ]
  181. }
  182. const {dateRange} = storeToRefs(publicData)
  183. const loading = ref(true)
  184. const getDataset = async () => {
  185. const resp = await getLineData({profile: shopInfo.profile.profile_id, start: dateRange.value[0], end: dateRange.value[1]})
  186. return resp.data
  187. }
  188. const initLine = async () => {
  189. chartObj = echarts.init(chartRef.value)
  190. const items = await getDataset()
  191. option.dataset.source = items
  192. XEUtils.arrayEach(metricsItems.value, info => {
  193. option.legend.selected[info.label] = false
  194. })
  195. for (const info of metrics.value) {
  196. option.legend.selected[info.label] = true
  197. }
  198. chartObj.setOption(option)
  199. loading.value = false
  200. }
  201. const getMetricsItems = async () => {
  202. const resp = await getCardData({start: dateRange.value[0], end: dateRange.value[1], profile: shopInfo.profile.profile_id})
  203. const data = resp.data
  204. metricsItems.value.length = 0
  205. XEUtils.arrayEach(spCampaignMetricsEnum, info => {
  206. const tmp: MetricData = {
  207. label: info.label,
  208. value: info.value,
  209. metricVal: data[info.value],
  210. gapVal: data[`gap${info.value}`],
  211. preVal: data[`prev${info.value}`],
  212. }
  213. metricsItems.value.push(tmp)
  214. })
  215. }
  216. const changeMetric = () => {
  217. const opt = buildChartOpt(option, metrics.value)
  218. chartObj.setOption(opt)
  219. }
  220. watch(
  221. dateRange,
  222. async () => {
  223. loading.value = true
  224. await getMetricsItems()
  225. const items = await getDataset()
  226. const opt = {dataset: {source: items}}
  227. chartObj.setOption(opt)
  228. loading.value = false
  229. }
  230. )
  231. const resizeChart = () => {
  232. chartObj.resize()
  233. }
  234. const addResize = () => {
  235. window.addEventListener('resize', resizeChart)
  236. }
  237. const removeResize = () => {
  238. window.removeEventListener('resize', resizeChart)
  239. }
  240. </script>
  241. <style scoped>
  242. .metrics-cards {
  243. display: flex;
  244. justify-content: space-between;
  245. align-items: flex-start;
  246. gap: 12px;
  247. width: 100%;
  248. }
  249. </style>