|
@@ -0,0 +1,397 @@
|
|
|
+<template>
|
|
|
+ <div v-loading="loading">
|
|
|
+ <el-row :gutter="5">
|
|
|
+ <el-col :span="24">
|
|
|
+ <div style="margin-left: 45%">
|
|
|
+ <span style="background: #3a83f7; width: 18px; height: 10px; margin-top: 8px; display: inline-block; border-radius: 3px;"></span>
|
|
|
+ <TextSelector v-model="barModelValue1" :options="barOptions1" @change="changeBarOne" style="margin-top: 5px; margin-left: 8px;"/>
|
|
|
+ <span style="background: #f19a37; width: 18px; height: 10px; margin-top: 8px; margin-left: 20px; display: inline-block; border-radius: 3px;"></span>
|
|
|
+ <TextSelector v-model="barModelValue2" :options="barOptions2" @change="changeBarTwo" style="margin-top: 5px; margin-left: 8px;"/>
|
|
|
+ </div>
|
|
|
+ <div ref="bar" style="height: 400px;"></div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { onMounted, ref, inject } from "vue"
|
|
|
+import * as echarts from "echarts"
|
|
|
+import TextSelector from '/@/components/TextSelector/index.vue'
|
|
|
+import { getAdStructureData } from "/@/views/adManage/sp/keywords/api"
|
|
|
+
|
|
|
+let barChart = ref()
|
|
|
+const bar = ref()
|
|
|
+const loading = ref(true)
|
|
|
+
|
|
|
+let dateRange = inject('dateRange')
|
|
|
+
|
|
|
+// 下拉框相关
|
|
|
+const barOptions1 = [
|
|
|
+ {
|
|
|
+ value: 'ACOS',
|
|
|
+ label: 'ACOS',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'ROAS',
|
|
|
+ label: 'ROAS',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'Spend',
|
|
|
+ label: '花费',
|
|
|
+ units: '$',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalSales',
|
|
|
+ label: '销售额',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalPurchases',
|
|
|
+ label: '订单数',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalUnitOrdered',
|
|
|
+ label: '销量',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'CPC',
|
|
|
+ label: '点击成本'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'CPA',
|
|
|
+ label: '订单成本'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'Impression',
|
|
|
+ label: '曝光量',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'Click',
|
|
|
+ label: '点击量',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'qwe',
|
|
|
+ label: '点击率'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: '转化率',
|
|
|
+ label: '转化率'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalSalesSameSKU',
|
|
|
+ label: '推广商品销售额'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalSalesOtherSKU',
|
|
|
+ label: '其他商品销售额'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalPurchasesSameSKU',
|
|
|
+ label: '推广商品订单数'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalPurchasesOtherSKU',
|
|
|
+ label: '其他商品订单数'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalUnitOrderedSameSKU',
|
|
|
+ label: '推广商品销量'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalUnitOrderedOtherSKU',
|
|
|
+ label: '其他商品销量'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TopOfSearchImpressionShare',
|
|
|
+ label: '搜索结果顶部展示份额'
|
|
|
+ },
|
|
|
+]
|
|
|
+let barModelValue1 = ref(barOptions1[0].value)
|
|
|
+
|
|
|
+const barOptions2 = [
|
|
|
+ {
|
|
|
+ value: 'ACOS',
|
|
|
+ label: 'ACOS',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'ROAS',
|
|
|
+ label: 'ROAS',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'Spend',
|
|
|
+ label: '花费',
|
|
|
+ units: '$',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalSales',
|
|
|
+ label: '销售额',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalPurchases',
|
|
|
+ label: '订单数',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalUnitOrdered',
|
|
|
+ label: '销量',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'CPC',
|
|
|
+ label: '点击成本'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'CPA',
|
|
|
+ label: '订单成本'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'Impression',
|
|
|
+ label: '曝光量',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'Click',
|
|
|
+ label: '点击量',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'qwe',
|
|
|
+ label: '点击率'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: '转化率',
|
|
|
+ label: '转化率'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalSalesSameSKU',
|
|
|
+ label: '推广商品销售额'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalSalesOtherSKU',
|
|
|
+ label: '其他商品销售额'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalPurchasesSameSKU',
|
|
|
+ label: '推广商品订单数'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalPurchasesOtherSKU',
|
|
|
+ label: '其他商品订单数'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalUnitOrderedSameSKU',
|
|
|
+ label: '推广商品销量'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TotalUnitOrderedOtherSKU',
|
|
|
+ label: '其他商品销量'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'TopOfSearchImpressionShare',
|
|
|
+ label: '搜索结果顶部展示份额'
|
|
|
+ },
|
|
|
+]
|
|
|
+let barModelValue2 = ref(barOptions2[2].value)
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ barChart = echarts.init(bar.value)
|
|
|
+
|
|
|
+ window.addEventListener('resize', resizeChart) // 监听窗口大小变化,调整图表大小
|
|
|
+ setTimeout(() => {
|
|
|
+ resizeChart()
|
|
|
+ }, 0)
|
|
|
+
|
|
|
+ await initBarData()
|
|
|
+ initChart()
|
|
|
+})
|
|
|
+
|
|
|
+// 获取总数据
|
|
|
+let resp = null
|
|
|
+
|
|
|
+async function setAdStructureData() {
|
|
|
+ resp = await getAdStructureData({ start: dateRange.value[0], end: dateRange.value[1], profile: '3006125408623189' })
|
|
|
+ console.log('resp.data', resp.data)
|
|
|
+ return resp.data
|
|
|
+}
|
|
|
+
|
|
|
+// 饼图总数据和柱状图总数据
|
|
|
+let barData = null
|
|
|
+let allData = null
|
|
|
+// 柱状图初始数据
|
|
|
+let ACOSList
|
|
|
+let SpendList
|
|
|
+let matchTypeList
|
|
|
+let matchTypeMapList
|
|
|
+
|
|
|
+async function initBarData() {
|
|
|
+ allData = await setAdStructureData()
|
|
|
+ barData = allData
|
|
|
+ // 柱状图初始化数据
|
|
|
+ ACOSList = barData.map(item => item.ACOS)
|
|
|
+ SpendList = barData.map(item => item.Spend)
|
|
|
+ // 将x轴映射为中文
|
|
|
+ matchTypeList = barData.map(item => item.matchType)
|
|
|
+ const matchTypeMap = {
|
|
|
+ 'BROAD': '关键词-广泛',
|
|
|
+ 'category': '品类',
|
|
|
+ 'EXACT': '关键词-精准',
|
|
|
+ 'asin': '商品',
|
|
|
+ 'PHRASE': '关键词-词组',
|
|
|
+ 'close-match': '紧密匹配',
|
|
|
+ 'loose-match': '广泛匹配',
|
|
|
+ 'substitutes': '同类商品',
|
|
|
+ 'complements': '关联商品'
|
|
|
+ }
|
|
|
+ matchTypeMapList = matchTypeList.map(item => matchTypeMap[item])
|
|
|
+ loading.value = false
|
|
|
+}
|
|
|
+
|
|
|
+// 重置图像
|
|
|
+let barFlag = ref()
|
|
|
+let barFlag2 = ref()
|
|
|
+let option
|
|
|
+let option2
|
|
|
+
|
|
|
+function changeBarOne(newValue) {
|
|
|
+ barModelValue1.value = newValue
|
|
|
+ barFlag.value = barModelValue1.value
|
|
|
+ const barValues = []
|
|
|
+ try {
|
|
|
+ for (let i = 0; i < barData.length; i++) {
|
|
|
+ const value = barData[i][barFlag.value]
|
|
|
+ barValues.push(value)
|
|
|
+ }
|
|
|
+ // barChart.clear()
|
|
|
+ option.series[0].data = barValues
|
|
|
+ barChart.setOption(option)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function changeBarTwo(newValue) {
|
|
|
+ barModelValue2.value = newValue
|
|
|
+ barFlag2.value = barModelValue2.value
|
|
|
+ const barValues = []
|
|
|
+ try {
|
|
|
+ for (let i = 0; i < barData.length; i++) {
|
|
|
+ const value = barData[i][barFlag2.value]
|
|
|
+ barValues.push(value)
|
|
|
+ }
|
|
|
+ // barChart.clear()
|
|
|
+ option.series[1].data = barValues
|
|
|
+ barChart.setOption(option)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化图表
|
|
|
+function initChart() {
|
|
|
+ // 柱状图配置
|
|
|
+ option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'cross',
|
|
|
+ label: {
|
|
|
+ backgroundColor: '#6a7985'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // legend: {data: ['数据1', '数据2'],},
|
|
|
+ toolbox: {
|
|
|
+ feature: {
|
|
|
+ saveAsImage: { yAxisIndex: 'none' }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ top: 50, right: 60, bottom: 50, left: 60,
|
|
|
+
|
|
|
+ },
|
|
|
+ xAxis: [
|
|
|
+ {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: true,
|
|
|
+ data: matchTypeMapList,
|
|
|
+ // axisLabel: {
|
|
|
+ // rotate: 30, // 将标签旋转45度
|
|
|
+ // fontSize: 12
|
|
|
+ // },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ yAxis: [
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ // name: '数据1',
|
|
|
+ // axisLabel: {
|
|
|
+ // formatter: '{value} %'
|
|
|
+ // },
|
|
|
+ axisLine: {
|
|
|
+ show: true,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#3a83f7' // 第一个 Y 轴的颜色
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ // name: '数据2',
|
|
|
+ splitLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ // axisLabel: {
|
|
|
+ // formatter: '{value} 单位2'
|
|
|
+ // },
|
|
|
+ axisLine: {
|
|
|
+ show: true,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#f19a37' // 第一个 Y 轴的颜色
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ // name: '数据1',
|
|
|
+ type: 'bar',
|
|
|
+ barWidth: '5%',
|
|
|
+ data: ACOSList,
|
|
|
+ yAxisIndex: 0,
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: '#3a83f7' },
|
|
|
+ { offset: 1, color: 'rgb(111, 209, 206)' },
|
|
|
+ ]),
|
|
|
+ // 柱状图圆角
|
|
|
+ borderRadius: [6, 6, 6, 6],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ // name: '数据2',
|
|
|
+ type: 'bar',
|
|
|
+ barWidth: '5%',
|
|
|
+ data: SpendList,
|
|
|
+ yAxisIndex: 1,
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: '#f19a37' },
|
|
|
+ { offset: 1, color: 'rgb(234,207,135)' },
|
|
|
+ ]),
|
|
|
+ // 柱状图圆角
|
|
|
+ borderRadius: [6, 6, 6, 6],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }
|
|
|
+ barChart.setOption(option)
|
|
|
+ resizeChart()
|
|
|
+}
|
|
|
+
|
|
|
+function resizeChart() {
|
|
|
+ barChart.resize()
|
|
|
+}
|
|
|
+
|
|
|
+defineExpose({ resizeChart })
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+
|
|
|
+</style>
|