|
@@ -9,7 +9,7 @@ import type {
|
|
|
} from '@/types/echarts/homeAnalysisChart'
|
|
|
import type { AnalysisSelectInfo } from '@/hooks/HomeSelect/useAnalysisSelect'
|
|
|
|
|
|
-import { computed, reactive, ref } from 'vue'
|
|
|
+import { computed, reactive, ref, watch } from 'vue'
|
|
|
import { useRequest } from '@/hooks/useRequest'
|
|
|
import { useHomeSelect } from '@/hooks/HomeSelect/useHomeSelect'
|
|
|
|
|
@@ -17,8 +17,10 @@ import Menu from '@/components/navigation/Menu.vue'
|
|
|
import CSelect from '@/components/form/CSelect.vue'
|
|
|
import HomeAnalysisLine from '@/components/echarts/HomeAnalysisLine.vue'
|
|
|
import axiosInstance from '@/utils/axios/axiosInstance'
|
|
|
+import AnimationNumber from '@/components/animationNumber/AnimationNumber.vue'
|
|
|
|
|
|
import '@/assets/css/statistic.css'
|
|
|
+import type { AxiosRequestConfig } from 'axios'
|
|
|
|
|
|
const { AllApi } = useRequest()
|
|
|
|
|
@@ -28,65 +30,50 @@ const {
|
|
|
productAnalySeleInfo,
|
|
|
legendSelectInfo,
|
|
|
leftToolsSelectInfo,
|
|
|
- analysisReqParams,
|
|
|
} = useHomeSelect()
|
|
|
|
|
|
+// 总览数据的自定义指标最多选择个数
|
|
|
+const maxSelectOverviewIndicator = 6
|
|
|
+
|
|
|
// 图表的数据配置
|
|
|
const analysisDataConfig: {
|
|
|
[key: string]: {
|
|
|
url: string
|
|
|
xAxisDataField: string
|
|
|
+ config: AxiosRequestConfig
|
|
|
}
|
|
|
} = {
|
|
|
projAnalysis: {
|
|
|
url: AllApi.mockChart,
|
|
|
xAxisDataField: 'stat_datetime',
|
|
|
+ config: {
|
|
|
+ params: {},
|
|
|
+ },
|
|
|
},
|
|
|
productAnalysis: {
|
|
|
url: AllApi.mockChartProduct,
|
|
|
xAxisDataField: 'date',
|
|
|
+ config: {
|
|
|
+ params: {},
|
|
|
+ },
|
|
|
},
|
|
|
}
|
|
|
|
|
|
-// 广告数据
|
|
|
-const overviewAdvertisingData = reactive<Array<overviewAdvertisingData>>([
|
|
|
- {
|
|
|
- name: 'ce1',
|
|
|
- title: '消耗(元)11',
|
|
|
- value: 98500.03,
|
|
|
- rate: 24,
|
|
|
- },
|
|
|
- {
|
|
|
- name: 'ce2',
|
|
|
- title: '消耗(元)22',
|
|
|
- value: 98500.03,
|
|
|
- rate: 24,
|
|
|
- },
|
|
|
- {
|
|
|
- name: 'ce3',
|
|
|
- title: '消耗(元)33',
|
|
|
- value: 98500.03,
|
|
|
- rate: 24,
|
|
|
- },
|
|
|
- {
|
|
|
- name: 'ce4',
|
|
|
- title: '消耗(元)44',
|
|
|
- value: 98500.03,
|
|
|
- rate: 24,
|
|
|
- },
|
|
|
- {
|
|
|
- name: 'ce5',
|
|
|
- title: '消耗(元)55',
|
|
|
- value: 98500.03,
|
|
|
- rate: 24,
|
|
|
- },
|
|
|
- {
|
|
|
- name: 'ce6',
|
|
|
- title: '消耗(元)66',
|
|
|
- value: 98500.03,
|
|
|
- rate: 24,
|
|
|
+// 总览数据的请求配置
|
|
|
+const overviewDataConfig: {
|
|
|
+ url: string
|
|
|
+ config: AxiosRequestConfig
|
|
|
+} = {
|
|
|
+ url: AllApi.mockOverview,
|
|
|
+ config: {
|
|
|
+ params: {},
|
|
|
},
|
|
|
-])
|
|
|
+}
|
|
|
+
|
|
|
+const statisticLoading = ref<boolean>(false) // 总览数据加载状态
|
|
|
+
|
|
|
+// 广告数据
|
|
|
+const overviewAdvertisingData = reactive<Array<overviewAdvertisingData>>([])
|
|
|
|
|
|
// 分析栏导航菜单
|
|
|
const dataAnalysisMenuList = reactive<Array<BaseMenu>>([
|
|
@@ -116,43 +103,46 @@ const chartLoading = ref<boolean>(true)
|
|
|
const chartData = reactive<Array<HomeAnalysisChartData>>([])
|
|
|
|
|
|
/**
|
|
|
- * @description: 当选择的数据发生变化时,重新获取数据
|
|
|
- * @param {*} newVal 新的值
|
|
|
- * @param {*} name 字段名
|
|
|
+ * @description: (暂时废弃,因为会导致更换指标的时候,数组的变化导致数据重新执行动画)
|
|
|
+ * 根据已选择自定义指标动态的加入广告数据概况
|
|
|
* @return {*}
|
|
|
*/
|
|
|
-const changeChartSelect = (newVal: AllOptionsVal, name: string) => {
|
|
|
- // 对于date字段特殊处理一下
|
|
|
- if (name === 'date') {
|
|
|
- analysisReqParams[analysisiMenuActive.value]['startTime'] = (
|
|
|
- newVal as DateOptionVal
|
|
|
- ).startTime
|
|
|
- analysisReqParams[analysisiMenuActive.value]['endTime'] = (
|
|
|
- newVal as DateOptionVal
|
|
|
- ).endTime
|
|
|
- } else {
|
|
|
- analysisReqParams[analysisiMenuActive.value][name] = newVal
|
|
|
- }
|
|
|
+// const overviewDataSelected = computed(() => {
|
|
|
+// // // 这里这样搞是为了做出动态加入的效果,而不是始终在原位置显示
|
|
|
+// let result: Array<overviewAdvertisingData> = []
|
|
|
+// overviewSelectInfo.customIndicatorSelect.value.forEach((item: string) => {
|
|
|
+// let finded = overviewAdvertisingData.find(data => data.name === item)
|
|
|
+// if (finded) {
|
|
|
+// result.push(finded)
|
|
|
+// }
|
|
|
+// })
|
|
|
+// return result;
|
|
|
+// })
|
|
|
|
|
|
- console.log(analysisReqParams[analysisiMenuActive.value])
|
|
|
- getChartData()
|
|
|
+/**
|
|
|
+ * @description: 创建图表的请求参数
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const createChartParams = () => {
|
|
|
+ let nowAnalysis = analysisSelectInfo[analysisiMenuActive.value]
|
|
|
+ let reqConfig = analysisDataConfig[analysisiMenuActive.value].config
|
|
|
+ for (let [_k, v] of Object.entries(nowAnalysis)) {
|
|
|
+ if (v.name === 'date') {
|
|
|
+ reqConfig.params['startTime'] = (v.value as DateOptionVal).startTime
|
|
|
+ reqConfig.params['endTime'] = (v.value as DateOptionVal).endTime
|
|
|
+ } else {
|
|
|
+ reqConfig.params[v.name] = v.value
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @description: 根据已选择自定义指标动态的加入广告数据概况
|
|
|
+ * @description: 当选择的数据发生变化时,重新获取数据
|
|
|
* @return {*}
|
|
|
*/
|
|
|
-const overviewDataSelected = computed(() => {
|
|
|
- // 这里这样搞是为了做出动态加入的效果,而不是始终在原位置显示
|
|
|
- let result: Array<overviewAdvertisingData> = []
|
|
|
- overviewSelectInfo.customIndicatorSelect.value.forEach((item: string) => {
|
|
|
- let finded = overviewAdvertisingData.find(data => data.name === item)
|
|
|
- if (finded) {
|
|
|
- result.push(finded)
|
|
|
- }
|
|
|
- })
|
|
|
- return result
|
|
|
-})
|
|
|
+const changeChartSelect = () => {
|
|
|
+ getChartData()
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* @description: 数据分析栏菜单切换
|
|
@@ -161,6 +151,7 @@ const overviewDataSelected = computed(() => {
|
|
|
*/
|
|
|
const analysisiMenuChange = (newMenu: string) => {
|
|
|
analysisiMenuActive.value = newMenu
|
|
|
+
|
|
|
getChartData()
|
|
|
}
|
|
|
|
|
@@ -170,12 +161,11 @@ const analysisiMenuChange = (newMenu: string) => {
|
|
|
*/
|
|
|
const getChartData = async () => {
|
|
|
try {
|
|
|
+ createChartParams() // 更新请求参数
|
|
|
chartLoading.value = true
|
|
|
const res = (await axiosInstance.get(
|
|
|
analysisDataConfig[analysisiMenuActive.value].url,
|
|
|
- {
|
|
|
- params: analysisReqParams[analysisiMenuActive.value],
|
|
|
- },
|
|
|
+ analysisDataConfig[analysisiMenuActive.value].config,
|
|
|
)) as ResponseInfo
|
|
|
if (res.code !== 0) throw new Error('获取图表数据失败')
|
|
|
chartData.splice(0, chartData.length, ...res.data)
|
|
@@ -192,7 +182,6 @@ const getChartData = async () => {
|
|
|
*/
|
|
|
const analysisLegendInfo = computed<Array<LegendInfo>>(() => {
|
|
|
let result: Array<LegendInfo> = []
|
|
|
- console.log(legendSelectInfo[analysisiMenuActive.value])
|
|
|
for (let [_k, v] of Object.entries(
|
|
|
legendSelectInfo[analysisiMenuActive.value],
|
|
|
)) {
|
|
@@ -205,7 +194,93 @@ const analysisLegendInfo = computed<Array<LegendInfo>>(() => {
|
|
|
return result
|
|
|
})
|
|
|
|
|
|
+/**
|
|
|
+ * @description: 创建新的自定义指标选择框的值
|
|
|
+ * @param {*} data 返回的数据
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const createIndicatorSelectInfo = (data: Array<overviewAdvertisingData>) => {
|
|
|
+ let options = data.map(item => {
|
|
|
+ return {
|
|
|
+ value: item.name,
|
|
|
+ label: item.title,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 形成新的值,也就是把所有的name都取出来
|
|
|
+ let values = data.slice(0, maxSelectOverviewIndicator).map(item => item.name)
|
|
|
+
|
|
|
+ // 更新自定义指标选项
|
|
|
+ let overviewOptions = overviewSelectInfo.customIndicatorSelect.options
|
|
|
+ overviewOptions.splice(0, overviewOptions.length, ...options)
|
|
|
+
|
|
|
+ // 更新值
|
|
|
+ let overviewValues = overviewSelectInfo.customIndicatorSelect.value
|
|
|
+ overviewValues.splice(0, overviewValues.length, ...values)
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 创建广告数据概况请求参数
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const createOverviewReqParams = () => {
|
|
|
+ let result: { [key: string]: any } = {}
|
|
|
+ for (let [k, v] of Object.entries(overviewSelectInfo)) {
|
|
|
+ // 除了自定义指标,另外两个选择框的值就作为请求参数
|
|
|
+ if (k !== 'customIndicatorSelect') {
|
|
|
+ if (v.name === 'date') {
|
|
|
+ // date选择框需要单独处理一下
|
|
|
+ result['startTime'] = v.value.startTime
|
|
|
+ result['endTime'] = v.value.endTime
|
|
|
+ } else {
|
|
|
+ result[v.name] = v.value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ overviewDataConfig.config.params = result
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 获取总览数据
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const getOverviewData = async () => {
|
|
|
+ try {
|
|
|
+ statisticLoading.value = true
|
|
|
+ createOverviewReqParams() // 更新请求参数
|
|
|
+ let res = (await axiosInstance.get(
|
|
|
+ overviewDataConfig.url,
|
|
|
+ overviewDataConfig.config,
|
|
|
+ )) as ResponseInfo
|
|
|
+ if (res.code !== 0) throw new Error('获取广告数据概况失败')
|
|
|
+ let data = res.data as Array<overviewAdvertisingData>
|
|
|
+ createIndicatorSelectInfo(data) // 根据返回的数据去更新自定义指标选项和值
|
|
|
+ overviewAdvertisingData.splice(0, overviewAdvertisingData.length, ...data)
|
|
|
+ } catch (err) {
|
|
|
+ console.log(err)
|
|
|
+ ElMessage.error('获取广告数据概况失败')
|
|
|
+ } finally {
|
|
|
+ statisticLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 改变总览数据框的筛选条件
|
|
|
+ * @param {*} _newSelect 新的筛选条件
|
|
|
+ * @param {*} name 筛选条件的名称
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const changeOverviewSelect = (_newSelect: any, name: string) => {
|
|
|
+ if (name === 'customIndicator') {
|
|
|
+ // console.log(_newSelect)
|
|
|
+
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ getOverviewData()
|
|
|
+}
|
|
|
+import StatisticCard from '@/components/statisticCard/StatisticCard.vue'
|
|
|
getChartData()
|
|
|
+getOverviewData()
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
@@ -218,44 +293,49 @@ getChartData()
|
|
|
</div>
|
|
|
<div class="overviewFilterBox">
|
|
|
<CSelect
|
|
|
- :multiple-limit="6"
|
|
|
+ :multiple-limit="maxSelectOverviewIndicator"
|
|
|
size="default"
|
|
|
:select-info="overviewSelectInfo"
|
|
|
+ @change-select="changeOverviewSelect"
|
|
|
></CSelect>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="dataOverview">
|
|
|
+ <div class="dataOverview" v-loading="statisticLoading">
|
|
|
<el-row :gutter="16">
|
|
|
- <el-col :span="4" v-for="item in overviewDataSelected">
|
|
|
- <template
|
|
|
+ <template v-for="item in overviewAdvertisingData">
|
|
|
+ <el-col
|
|
|
v-if="
|
|
|
overviewSelectInfo.customIndicatorSelect.value.includes(
|
|
|
item.name,
|
|
|
)
|
|
|
"
|
|
|
+ :span="4"
|
|
|
>
|
|
|
- <div class="statistic-card" html>
|
|
|
- <el-statistic :value="item.value" :precision="2">
|
|
|
- <template #title>
|
|
|
- <div style="display: inline-flex; align-items: center">
|
|
|
- {{ item.title }}
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-statistic>
|
|
|
- <div class="statistic-footer">
|
|
|
- <div class="footer-item">
|
|
|
+ <StatisticCard
|
|
|
+ :title="item.title"
|
|
|
+ :value="item.value"
|
|
|
+ :transition="true"
|
|
|
+ >
|
|
|
+ <template #footer>
|
|
|
+ <div>
|
|
|
<span>环比</span>
|
|
|
- <span class="green">
|
|
|
- {{ item.rate }}%
|
|
|
+ <span v-if="item.rate < 0" class="green">
|
|
|
+ <el-icon>
|
|
|
+ <CaretBottom />
|
|
|
+ </el-icon>
|
|
|
+ {{ Math.abs(item.rate) }}%
|
|
|
+ </span>
|
|
|
+ <span v-else class="red">
|
|
|
<el-icon>
|
|
|
<CaretTop />
|
|
|
</el-icon>
|
|
|
+ {{ item.rate }}%
|
|
|
</span>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-col>
|
|
|
+ </template>
|
|
|
+ </StatisticCard>
|
|
|
+ </el-col>
|
|
|
+ </template>
|
|
|
</el-row>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -284,11 +364,13 @@ getChartData()
|
|
|
class="dataTools"
|
|
|
v-if="analysisiMenuActive === 'productAnalysis'"
|
|
|
>
|
|
|
- <CSelect
|
|
|
- class="dataSource"
|
|
|
- @change-select="changeChartSelect"
|
|
|
- :select-info="leftToolsSelectInfo"
|
|
|
- ></CSelect>
|
|
|
+ <div class="dataToolItem"></div>
|
|
|
+ <div class="dataToolItem">
|
|
|
+ <CSelect
|
|
|
+ class="dataSource"
|
|
|
+ :select-info="leftToolsSelectInfo"
|
|
|
+ ></CSelect>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="legendTools">
|
|
|
<CSelect
|
|
@@ -311,7 +393,6 @@ getChartData()
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <!-- {{ allChartSelectInfo }} -->
|
|
|
<div class="topArea"></div>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -321,7 +402,7 @@ getChartData()
|
|
|
padding-top: 3vh;
|
|
|
}
|
|
|
.advertisingDataOverview {
|
|
|
- width: 85%;
|
|
|
+ width: 1320px;
|
|
|
margin: 0 auto;
|
|
|
padding: 16px 16px 24px;
|
|
|
background-color: #fff;
|
|
@@ -354,12 +435,18 @@ getChartData()
|
|
|
}
|
|
|
|
|
|
.dataOverview {
|
|
|
- width: 100%;
|
|
|
+ height: 120px;
|
|
|
+ padding: 10px 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.statistic-card {
|
|
|
+ background-color: rgb(232, 243, 255);
|
|
|
+ margin: 10px 5px;
|
|
|
}
|
|
|
|
|
|
.advertisingDataAnalysis {
|
|
|
position: relative;
|
|
|
- width: 85%;
|
|
|
+ width: 1320px;
|
|
|
margin: 0 auto;
|
|
|
padding: 16px 16px 24px;
|
|
|
background-color: #fff;
|
|
@@ -401,6 +488,7 @@ getChartData()
|
|
|
/* display: flex; */
|
|
|
/* align-items: center; */
|
|
|
margin-top: 24px;
|
|
|
+ /* padding: 24px 0; */
|
|
|
}
|
|
|
|
|
|
.legendTools {
|
|
@@ -409,15 +497,14 @@ getChartData()
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
+.dataToolItem {
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
.dataTools {
|
|
|
position: relative;
|
|
|
|
|
|
- /* display: flex; */
|
|
|
- /* justify-content: space-between; */
|
|
|
-}
|
|
|
-
|
|
|
-.dataSource {
|
|
|
- position: absolute;
|
|
|
- right: 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
}
|
|
|
</style>
|