提交 9e8d1c4f authored 作者: lidongxu's avatar lidongxu

refactor(cmm): 蝉妈妈页面又优化了一下

同上
上级 7915b8e2
export const useDatePickerOptions = () => { export const useDatePickerOptions = () => {
const nowMouth = [new Date().setDate((new Date().getDate() - 30)), new Date().setDate((new Date().getDate() - 1))]
const pickerOptions = ref([// 日期选项配置 const pickerOptions = ref([// 日期选项配置
{ {
text: '最近一周', text: '最近一周',
...@@ -19,6 +20,7 @@ export const useDatePickerOptions = () => { ...@@ -19,6 +20,7 @@ export const useDatePickerOptions = () => {
} }
]) ])
return { return {
nowMouth,
pickerOptions pickerOptions
} }
} }
\ No newline at end of file
...@@ -21,10 +21,6 @@ const props = defineProps({ ...@@ -21,10 +21,6 @@ const props = defineProps({
type: String, type: String,
default: '600px' default: '600px'
}, },
autoResize: {
type: Boolean,
default: true
},
chartData: { chartData: {
type: Object, type: Object,
required: true required: true
...@@ -93,6 +89,7 @@ const setOptions = () => { ...@@ -93,6 +89,7 @@ const setOptions = () => {
} }
} }
] ]
// 根据图例是否显示,设置 y 轴名字的值
yAxis.filter(yObj => { yAxis.filter(yObj => {
return props.chartData.legend.some(o => { return props.chartData.legend.some(o => {
const target = o.data.find(o => { const target = o.data.find(o => {
...@@ -102,6 +99,7 @@ const setOptions = () => { ...@@ -102,6 +99,7 @@ const setOptions = () => {
else yObj.name = target.name.split('-')[1] else yObj.name = target.name.split('-')[1]
}) })
}) })
// 设置图表选项
chart.value.setOption({ chart.value.setOption({
xAxis: { xAxis: {
type: 'category', type: 'category',
...@@ -165,18 +163,6 @@ const setOptions = () => { ...@@ -165,18 +163,6 @@ const setOptions = () => {
}); });
return tooltip; return tooltip;
} }
// padding: [5, 10],
// formatter: (params) => {
// let tooltip = '';
// params.forEach((item) => {
// if (item.seriesName.split('-')[1] === '销售额') {
// tooltip += item.marker + item.seriesName + ': ' + (this.myThousand ? convertToUnit(item.value, true) : toFixed2(item.value) + '元') + '<br>';
// } else if (item.seriesName.split('-')[1] === '观看人次') {
// tooltip += item.marker + item.seriesName + ': ' + toFixed2(item.value) + (this.myThousand ? '' : '') + '<br>';
// }
// });
// return tooltip;
// }
}, },
yAxis, yAxis,
series: props.chartData.series series: props.chartData.series
...@@ -191,19 +177,15 @@ watchEffect(() => { ...@@ -191,19 +177,15 @@ watchEffect(() => {
setOptions() setOptions()
}) })
const initChart = () => {
chart.value = echarts.init(echartsRef.value)
}
const resize = () => {
chart.value.resize()
}
useWindowResize(resize)
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
initChart() chart.value = echarts.init(echartsRef.value)
}) })
}) })
useWindowResize(() => {
chart.value.resize()
})
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (!chart.value) { if (!chart.value) {
return return
......
<template> <template>
<div class="tabs-container"> <div class="tabs-container">
<el-form :model="queryParams" <el-form :model="queryParams"
inline inline>
size="default">
<el-form-item label="直播间"> <el-form-item label="直播间">
<el-select v-model="queryParams.brandList" <el-select v-model="queryParams.brandList"
@change="queryChangeFn"
multiple multiple
clearable clearable
collapse-tags collapse-tags
collapse-tags-tooltip> collapse-tags-tooltip
@change="queryChangeFn">
<el-option v-for="str in brandList" <el-option v-for="str in brandList"
:label="str" :label="str"
:value="str"> :value="str">
...@@ -43,7 +42,8 @@ ...@@ -43,7 +42,8 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="chart_wrap" v-loading="loading"> <div class="chart_wrap"
v-loading="loading">
<template v-if="queryParams.brandList.length > 0 && queryParams.typeList.length > 0"> <template v-if="queryParams.brandList.length > 0 && queryParams.typeList.length > 0">
<group-legend :legendData="chartData.legend" <group-legend :legendData="chartData.legend"
@click-item="legendChangeFn"></group-legend> @click-item="legendChangeFn"></group-legend>
...@@ -64,19 +64,16 @@ import { getCmmListAPI } from '@/api' ...@@ -64,19 +64,16 @@ import { getCmmListAPI } from '@/api'
import { generatorDayList, parseTime, getAdditionalColor, resetObjValue } from '@/utils' import { generatorDayList, parseTime, getAdditionalColor, resetObjValue } from '@/utils'
import { useDatePickerOptions } from '@/hooks' import { useDatePickerOptions } from '@/hooks'
// 静态数据 // 静态数据
const dateList = [new Date().setDate((new Date().getDate() - 30)), new Date().setDate((new Date().getDate() - 1))] // 最近 30 日日期数组
const dataTypeList = ['销售额', '观看人次'] // 数据类型
// 页面使用数据
const brandList = ref([])// 直播间列表
const typeList = ref(dataTypeList) // 数据类型列表
const { pickerOptions } = useDatePickerOptions()
const loading = ref(true) const loading = ref(true)
const brandList = ref([]) // 直播间列表
const typeList = ref(['销售额', '观看人次']) // 数据类型列表
const { pickerOptions, nowMouth } = useDatePickerOptions() // 日期快捷方式
const queryParams = reactive({ // 查询表单 const queryParams = reactive({ // 查询表单
brandList: [], brandList: [],
date: dateList, date: nowMouth,
typeList: [dataTypeList[0]] typeList: [typeList.value[0]]
}) })
const allChartData = reactive({ // 图表所有数据 const allChartData = reactive({ // 图表所有数据
...@@ -84,26 +81,28 @@ const allChartData = reactive({ // 图表所有数据 ...@@ -84,26 +81,28 @@ const allChartData = reactive({ // 图表所有数据
legend: [], legend: [],
series: [] series: []
}) })
const chartData = reactive({ // 图表内要用的数据 const chartData = reactive({ // 图表使用数据
xAxis: [], xAxis: [],
legend: [], legend: [],
series: [] series: []
}) })
// 获取数据 // 获取数据
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
// 重置数据源 // 重置数据源
resetObjValue(allChartData) resetObjValue(allChartData)
// 获取 x 轴时间 // 请求数据
allChartData.xAxis = generatorDayList(queryParams.date[0], queryParams.date[1])
const { data } = await getCmmListAPI({ const { data } = await getCmmListAPI({
startDate: parseTime(queryParams.date[0], '{y}-{m}-{d}'), startDate: parseTime(queryParams.date[0], '{y}-{m}-{d}'),
endDate: parseTime(queryParams.date[1], '{y}-{m}-{d}') endDate: parseTime(queryParams.date[1], '{y}-{m}-{d}')
}) })
// 获取 x 轴时间
allChartData.xAxis = generatorDayList(queryParams.date[0], queryParams.date[1])
// 获取 legend 和 series 数据
data.map((list, index) => { data.map((list, index) => {
// list:每个直播间 // list:每个直播间
// 按索引拿到颜色
let color = getAdditionalColor(index) let color = getAdditionalColor(index)
// 每个系列对象 // 每个系列对象
const saleObj = { const saleObj = {
...@@ -145,6 +144,10 @@ const getList = async () => { ...@@ -145,6 +144,10 @@ const getList = async () => {
gkrcObj.data.push(0) gkrcObj.data.push(0)
} }
}) })
// 添加系列数据
allChartData.series.push(saleObj)
allChartData.series.push(gkrcObj)
// 添加图例数据 // 添加图例数据
allChartData.legend.push({ allChartData.legend.push({
data: [{ data: [{
...@@ -162,9 +165,6 @@ const getList = async () => { ...@@ -162,9 +165,6 @@ const getList = async () => {
}], }],
orient: 'verticalAlign' orient: 'verticalAlign'
}) })
// 添加系列数据
allChartData.series.push(saleObj)
allChartData.series.push(gkrcObj)
}) })
loading.value = false loading.value = false
return data return data
...@@ -239,6 +239,7 @@ init() ...@@ -239,6 +239,7 @@ init()
// 筛选条件改变了 // 筛选条件改变了
const queryChangeFn = async (arg) => { const queryChangeFn = async (arg) => {
// 日期改变需要后台重新获取,其他改因为数据都给前台了,自己筛选
if (arg === 'date' && queryParams.date) { if (arg === 'date' && queryParams.date) {
await getList() await getList()
} }
......
...@@ -70,8 +70,8 @@ ...@@ -70,8 +70,8 @@
</template> </template>
<script setup> <script setup>
import GradientArea from './GradientArea.vue'; import GradientArea from '../components/GradientArea.vue';
import TableList from './TableList.vue'; import TableList from '../components/TableList.vue';
import { getComPrdListAPI, getSycmListAPI } from '@/api' import { getComPrdListAPI, getSycmListAPI } from '@/api'
import { generatorDayList, parseTime, getAdditionalColor, resetObjValue } from '@/utils' import { generatorDayList, parseTime, getAdditionalColor, resetObjValue } from '@/utils'
import { useDatePickerOptions } from '@/hooks' import { useDatePickerOptions } from '@/hooks'
......
<template>
<div ref="echartsRef"
:class="className"
:style="{ height: height, width: width }" />
</template>
<script setup>
import * as echarts from 'echarts'
import { formatNumberWithUnit } from '@/utils'
import { useWindowResize } from '@/hooks'
const props = defineProps({
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '600px'
},
autoResize: {
type: Boolean,
default: true
},
chartData: {
type: Object,
required: true
}
})
const echartsRef = ref(null)
const chart = shallowRef(null)
let myThousand = false // 是否显示万单位
let isArea = ref(true) // 是否面积图
const emits = defineEmits(['changeType'])
const setOptions = () => {
// 面积图是否切换
const seriesResult = props.chartData.series.map(o => {
if (!isArea.value) {
const obj = { ...o }
delete obj.areaStyle
delete obj.lineStyle
return obj
} else {
return o
}
})
chart.value.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
},
formatter: function (params) {
let tooltip = '';
params.forEach((item) => {
// 获取系列颜色
var color = item.color;
// 拼接提示内容
if (item.seriesName.split('-')[1].includes('速')) {
tooltip += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + color + ';"></span>' + item.seriesName + ': ' + formatNumberWithUnit({
value: item.value,
carry: false,
round: false,
pos: false,
des: '%'
}) + '<br>';
} else {
tooltip += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + color + ';"></span>' + item.seriesName + ':' + formatNumberWithUnit({
value: item.value,
des: '人'
}) + '<br>';
}
});
return tooltip;
}
},
// legend: {
// data: props.chartData.legend
// },
toolbox: {
feature: {
saveAsImage: {},
magicType: {
type: ['stack', 'tiled'] // 切换图表类型
},
myTool1: {
show: true,
title: '切换表格',
icon: 'path://M5,5 L5,15 L15,15 L15,5 Z M20,5 L20,15 L30,15 L30,5 Z M5,20 L5,30 L15,30 L15,20 Z M20,20 L20,30 L30,30 L30,20 Z',
onclick: () => {
emits('changeType', 'table')
}
},
myTool2: {
show: true,
title: '面积/折线图',
icon: 'path://M5,5 L5,30 L15,30 L25,20 L35,30 L45,30 L45,5 Z',
onclick: () => {
isArea.value = !isArea.value
}
}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
// type: 'category',
// boundaryGap: false,
data: props.chartData.xAxis
}
],
yAxis: [
{
type: 'value'
}
],
series: seriesResult
}, true)
}
watchEffect(() => {
if (!chart.value) return
myThousand = props.chartData.series?.some(o => {
return o.data.some(num => num >= 10000)
})
setOptions()
})
const initChart = () => {
chart.value = echarts.init(echartsRef.value)
}
const resize = () => {
chart.value.resize()
}
useWindowResize(resize)
onMounted(() => {
nextTick(() => {
initChart()
})
})
onBeforeUnmount(() => {
if (!chart.value) {
return
}
chart.value.dispose()
chart.value = null
})
</script>
\ No newline at end of file
<template>
<div class="toolbar">
<right-toolbar :search="false"
@queryTable="queryTable">
<el-tooltip class="item"
effect="dark"
content="日期合并/分散"
placement="top">
<el-button circle
icon="Calendar"
@click="dateMergeFn()" />
</el-tooltip>
<el-tooltip class="item"
effect="dark"
content="切换图表"
placement="top">
<el-button circle
icon="Histogram"
@click="changeType()" />
</el-tooltip>
</right-toolbar>
</div>
<el-table :data="data"
style="width: 100%">
<el-table-column prop="platformStore"
label="店铺" />
<el-table-column prop="date"
label="日期"
v-if="!dateMerge" />
<el-table-column v-for="str in column"
:prop="columnKey[str]"
:label="str"
:formatter="formatterFn" />
</el-table>
</template>
<script lang="ts"
setup>
const columnKey = {
'支付买家数': 'zfmj',
'交易增速': 'jyzs',
'独立访客范围': 'uv',
'流量增速': 'llzs'
}
const props = defineProps({
column: {
type: Object,
default: () => {
return {}
},
},
data: {
type: Array,
default: () => {
return []
},
},
dateMerge: { // 是否把日期数据合并
type: Boolean,
default: false,
}
})
const formatterFn = (row, column, cellValue) => {
let result = cellValue
if (column.property === 'jyzs' || column.property === 'llzs') {
result += '%'
}
if (props.dateMerge) {
result += ' / 平均每日'
}
return result
}
const emits = defineEmits(['changeType', 'queryTable', 'dateMerge'])
const queryTable = () => {
emits('queryTable')
}
const changeType = () => {
emits('changeType', 'charts')
}
const dateMergeFn = () => {
emits('dateMerge')
}
</script>
<style scoped
style="sass">
.toolbar {
float: right;
}
</style>
\ No newline at end of file
...@@ -68,8 +68,8 @@ ...@@ -68,8 +68,8 @@
</template> </template>
<script setup> <script setup>
import GradientArea from './GradientArea.vue'; import GradientArea from '../components/GradientArea.vue';
import TableList from './TableList.vue'; import TableList from '../components/TableList.vue';
import { getStoreListAPI, getSycmStoreListAPI } from '@/api' import { getStoreListAPI, getSycmStoreListAPI } from '@/api'
import { generatorDayList, parseTime, getAdditionalColor, resetObjValue } from '@/utils' import { generatorDayList, parseTime, getAdditionalColor, resetObjValue } from '@/utils'
import { useDatePickerOptions } from '@/hooks' import { useDatePickerOptions } from '@/hooks'
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论