123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- <template>
- <div v-loading="loading">
- <MetricsCards v-model="metrics" :metric-items="metricsItems" @change="changeMetric"></MetricsCards>
- <div style="height: 350px;" ref="chartRef"></div>
- </div>
- </template>
- <script lang="ts" setup>
- import { ref,onMounted, onBeforeUnmount, Ref, unref, watch, computed } from 'vue'
- import * as echarts from 'echarts'
- import { spCampaignMetricsEnum } from '/@/views/adManage/utils/enum.js'
- import MetricsCards from '/@/components/MetricsCards/index.vue'
- import XEUtils from 'xe-utils'
- import { buildChartOpt, parseQueryParams } from '/@/views/adManage/utils/tools.js'
- defineOptions({
- name: "DataTendencyChart"
- })
- interface Props {
- fetchCard: Function,
- fetchLine: Function,
- fetchLineMonth?: Function,
- fetchLineWeek?: Function,
- query: {[key: string]: any},
- initMetric?: ShowMetric[],
- metricEnum?: {[key: string]: string}[]
- }
- const props = withDefaults(defineProps<Props>(), {
- initMetric: () => [
- {metric: 'Impression', color: '#0085ff', 'label': '曝光量'},
- {metric: 'Click', color: '#3fd4cf', 'label': '点击量'},
- {metric: 'Spend', color: '#ff9500', 'label': '花费'},
- ],
- metricEnum: () => spCampaignMetricsEnum
- })
- const metrics = ref(props.initMetric)
- // const shopInfo = useShopInfo()
- // const publicData = usePublicData()
- // const { dateRange } = storeToRefs(publicData)
- const metricsItems: Ref<MetricData[]> = ref([])
- let chartObj:any
- const chartRef = ref()
- const statDim = ref('day')
- const option: any = {
- dataset: {
- source: []
- },
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- label: {
- backgroundColor: '#6a7985'
- }
- }
- },
- legend: {
- selected: {}, // 控制显隐
- show: false
- },
- grid: {
- top: 50, right: 150, bottom: 30, left: 65,
- },
- xAxis: {
- type: 'category'
- },
- yAxis: [
- {
- id: 0,
- type: 'value',
- name: '',
- splitLine: {
- show: true // 设置显示分割线
- },
- axisLine: {
- show: true,
- lineStyle: { color: '' }
- },
- show: true
- },
- {
- id: 1,
- type: 'value',
- name: '',
- position: 'right',
- splitLine: {
- show: false
- },
- axisLine: {
- show: true,
- lineStyle: {
- color: ''
- }
- },
- show: true
- },
- {
- id: 2,
- type: 'value',
- position: 'right',
- offset: 90,
- name: '',
- splitLine: {
- show: false
- },
- axisLine: {
- show: true,
- lineStyle: {
- color: ''
- }
- },
- show: true
- }
- ],
- series: [
- {
- id: 0,
- name: '',
- type: 'bar',
- encode: {
- x: 'Name',
- y: ''
- },
- barWidth: '20px',
- yAxisIndex: 0,
- itemStyle: {
- color: '',
- borderRadius: [6, 6, 6, 6],
- }
- },
- {
- id: 1,
- name: '',
- type: 'line',
- encode: {
- x: 'Name',
- y: ''
- },
- symbolSize: 6,
- symbol: 'circle',
- smooth: true,
- yAxisIndex: 1,
- itemStyle: {
- // color: '#ff9500',
- // borderColor: '#ff9500'
- },
- areaStyle: {
- // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- // { offset: 0, color: '#3fd4cf53' },
- // { offset: 1, color: '#3fd4cf03' },
- // ]),
- },
- emphasis: {
- focus:'series'
- }
- },
- {
- id: 2,
- name: '',
- type: 'line',
- encode: {
- x: 'Name',
- y: ''
- },
- symbolSize: 6,
- symbol: 'circle',
- smooth: true,
- yAxisIndex: 2,
- itemStyle: {},
- areaStyle: {},
- emphasis: {
- focus:'series'
- }
- }
- ]
- }
- const loading = ref(true)
- const queryParams = computed(() => parseQueryParams(props.query))
- onMounted(() => {
- getMetricsItems()
- addResize()
- // initLine()
- setTimeout(() => { initLine() }, 0)
- })
- onBeforeUnmount(() => {
- if(chartObj) {
- chartObj.dispose()
- chartObj = null
- }
- removeResize()
- })
- const initLine = async () => {
- chartObj = echarts.init(chartRef.value)
- const items = await getDataset()
- option.dataset.source = items
- XEUtils.arrayEach(option.series, (info:any, index) => {
- const color = metrics.value[index].color
- info.name = metrics.value[index].label
- info.encode.y = metrics.value[index].metric
- if (info.type === 'bar') {
- info.itemStyle.color = color
- } else {
- info.itemStyle = { color: color, borderColor: color }
- info.areaStyle = {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: color + '53' },
- { offset: 1, color: color + '03' },
- ])
- }
- }
- })
- XEUtils.arrayEach(option.yAxis, (info:any, index) => {
- info.name = metrics.value[index].label
- info.axisLine.lineStyle.color = metrics.value[index].color
- })
- XEUtils.arrayEach(props.metricEnum, info => {
- option.legend.selected[info.label] = false
- })
- for(const info of metrics.value) {
- option.legend.selected[info.label] = true
- }
- // console.log(option)
- chartObj.setOption(option)
- loading.value = false
- }
- const getDataset = async () => {
- if (statDim.value === 'week') {
- if (props.fetchLineWeek) {
- const resp = await props.fetchLineWeek(queryParams.value)
- return resp.data
- }
- } else if (statDim.value === 'month') {
- if (props.fetchLineMonth) {
- const resp = await props.fetchLineMonth(queryParams.value)
- return resp.data
- }
- } else {
- const resp = await props.fetchLine(queryParams.value)
- return resp.data
- }
- }
- const getMetricsItems = async () => {
- const resp = await props.fetchCard(queryParams.value)
- const data = resp.data
- metricsItems.value.length = 0
- XEUtils.arrayEach(props.metricEnum, info => {
- const tmp:MetricData = {
- label: info.label,
- value: info.value,
- metricVal: data[info.value],
- gapVal: data[`gap${info.value}`],
- preVal: data[`prev${info.value}`],
- }
- metricsItems.value.push(tmp)
- })
- }
- const changeMetric = () => {
- const opt = buildChartOpt(option, metrics.value)
- chartObj.setOption(opt)
- }
- const changeStatDim = async () => {
- loading.value = true
- let source = await getDataset()
- if (source.length > 0) {
- chartObj.setOption({dataset: {source: source}})
- }
- loading.value = false
- }
- watch(
- props.query,
- async () => {
- // console.log("------watch-----queryParams", props.query)
- loading.value = true
- await getMetricsItems()
- const items = await getDataset()
- const opt = { dataset: { source: items } }
- chartObj.setOption(opt)
- loading.value = false
- }
- )
- const resizeChart = () => { chartObj.resize() }
- const addResize = () => { window.addEventListener('resize', resizeChart) }
- const removeResize = () => { window.removeEventListener('resize', resizeChart) }
- </script>
- <style scoped>
- .metrics-cards {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- gap: 12px;
- width: 100%;
- }
- .chart-button-group {
- display: flex;
- justify-content: flex-end;
- margin-top: 5px;
- }
- </style>
|