dataTendency.vue 5.0 KB

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