Selaa lähdekoodia

更新首页图表,更新首页下拉选择框

fxs 7 kuukautta sitten
vanhempi
commit
f09ff6a324

+ 3 - 0
components.d.ts

@@ -7,6 +7,7 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
+    CSelect: typeof import('./src/components/form/CSelect.vue')['default']
     CustomDialog: typeof import('./src/components/dialog/customDialog.vue')['default']
     CustomIndicatorDialog: typeof import('./src/components/dialog/customIndicatorDialog.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
@@ -32,6 +33,8 @@ declare module 'vue' {
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    HomeAnalysis: typeof import('./src/components/echarts/homeAnalysis.vue')['default']
+    HomeAnalysisLine: typeof import('./src/components/echarts/HomeAnalysisLine.vue')['default']
     IconIcBaselineVisibility: typeof import('~icons/ic/baseline-visibility')['default']
     IconIcBaselineVisibilityOff: typeof import('~icons/ic/baseline-visibility-off')['default']
     IconMaterialSymbolsLightLogout: typeof import('~icons/material-symbols-light/logout')['default']

+ 1 - 0
package-lock.json

@@ -11,6 +11,7 @@
         "@element-plus/icons-vue": "^2.3.1",
         "echarts": "^5.5.1",
         "element-plus": "^2.8.5",
+        "lodash": "^4.17.21",
         "pinia": "^2.2.4",
         "vue": "^3.5.11",
         "vue-router": "^4.4.5"

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     "@element-plus/icons-vue": "^2.3.1",
     "echarts": "^5.5.1",
     "element-plus": "^2.8.5",
+    "lodash": "^4.17.21",
     "pinia": "^2.2.4",
     "vue": "^3.5.11",
     "vue-router": "^4.4.5"

+ 224 - 0
src/components/echarts/HomeAnalysisLine.vue

@@ -0,0 +1,224 @@
+<script setup lang="ts">
+import type { EChartsOption, SeriesOption } from 'echarts'
+import type { LegendInfo } from '@/types/echarts/homeAnalysisChart'
+
+import { onMounted, ref, shallowRef, watch, useAttrs } from 'vue'
+import { cloneDeep } from 'lodash'
+import { nextTick } from 'vue'
+import { debounceFunc } from '@/utils/common'
+import echarts from './index'
+
+interface Props {
+  loading: boolean
+  legend: Array<LegendInfo>
+  data: Array<any>
+}
+
+const props = defineProps<Props>()
+
+/**
+ * @description: 格式化tooltip
+ * @param {*} params 表格数据
+ * @return {*}
+ */
+// const formatterTooltip = (params: any) => {
+//   let circle = `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color:`
+//   let result = `<span style="font-weight:bold;">${params[0].axisValueLabel}</span>`
+
+//   params.map((item, index) => {
+//     let data = `${circle}${colorList[index]}"></span>
+//     <span >
+//     <span  style="display: inline-block;  box-sizing: border-box;
+//   padding-right: 50px;">${item['seriesName']}</span><span>${item['value']}<span>`
+//     result += `<br/>${data}`
+//   })
+//   return result
+// }
+
+// 颜色
+const colorList = [
+  '#00e070',
+  '#1495eb',
+  '#993333', // Dark Red
+  '#FFD700', // Bright Yellow
+  '#FF00FF', // Magenta
+  '#FFA500', // Orange
+  '#800080', // Dark Purple
+  '#A52A2A', // Brown
+  '#FF4500', // Orange Red
+  '#FF6347', // Tomato
+  '#B22222', // Firebrick
+  '#FF1493', // Deep Pink
+]
+
+let baseOptions: EChartsOption = {
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true,
+  },
+  toolbox: {
+    feature: {
+      saveAsImage: {},
+    },
+  },
+  xAxis: {
+    type: 'category',
+
+    axisLabel: {
+      showMaxLabel: true,
+    },
+    axisTick: {
+      alignWithLabel: true,
+    },
+  },
+  yAxis: {
+    type: 'value',
+    minInterval: 1,
+  },
+  tooltip: {
+    trigger: 'axis',
+  },
+  series: [],
+}
+
+let baseSeries: SeriesOption = {
+  symbol: 'circle',
+  symbolSize: 5,
+  showSymbol: false,
+  // itemStyle要在lineStyle前面,这个item会把line的样式覆盖掉,并且必须要有line,不然也会被item替换掉
+  itemStyle: {
+    color: 'rgb(255,255,255)',
+    borderColor: '#1495eb', // symbol边框颜色
+    borderWidth: 2, // symbol边框宽度
+  },
+  lineStyle: {
+    color: '#1495eb',
+  },
+  name: '',
+  data: [],
+  type: 'line',
+  smooth: false,
+}
+
+// 图表dom对象
+const chartRef = ref<HTMLElement>()
+
+// 图表实例
+const chartInstance = shallowRef<echarts.ECharts>()
+
+// 图表尺寸变化的观察者
+let chartSizeOb: ResizeObserver | null = null
+
+/**
+ * @description: 图表和图表实例是否都存在
+ * @return {*}
+ */
+const isExistChart = (): boolean => {
+  if (chartRef.value && chartInstance.value) return true
+  return false
+}
+
+/**
+ * @description: 更改图的加载状态
+ * @param {*} newState
+ * @return {*}
+ */
+const changeChartsLoading = (newState: boolean) => {
+  if (!isExistChart()) return
+  if (newState) chartInstance.value!.showLoading()
+  else chartInstance.value!.hideLoading()
+}
+
+/**
+ * @description: 更新图表大小
+ * @return {*}
+ */
+const chartResize = () => {
+  nextTick(() => {
+    chartInstance.value?.resize()
+  })
+}
+
+/**
+ * @description: 初始化图表的信息
+ * @return {*}
+ */
+const initChart = () => {
+  if (!chartRef.value) return
+
+  chartInstance.value = echarts.init(chartRef.value)
+  // 只监听window会导致当侧边栏缩放时,dom大小变化但无法resize
+  // 所以需要使用ovserver对整个dom进行监听
+  const debounceResize = debounceFunc(chartResize, 300)
+  chartSizeOb = new ResizeObserver(debounceResize)
+  chartSizeOb.observe(chartRef.value!)
+}
+
+const initOptions = () => {
+  if (!isExistChart()) return
+  chartInstance.value!.clear()
+  if (props.data.length > 0) {
+    // ;(baseOptions.series as SeriesOption[])[0].data = props.data
+    let finalSeriesData: SeriesOption[] = []
+    props.legend.forEach((item, index) => {
+      let newSeries: SeriesOption = cloneDeep(baseSeries)
+      let cData = cloneDeep(props.data)
+
+      let newData = cData.map((item: any) => {
+        return item[props.legend[index].value]
+      })
+      newSeries.name = item.value
+      newSeries.data = newData
+      newSeries.lineStyle!.color = item.color
+      newSeries.itemStyle!.color = colorList[index]
+      finalSeriesData.push(newSeries)
+    })
+    baseOptions.series = finalSeriesData
+    console.log(JSON.parse(JSON.stringify(baseOptions)))
+  } else {
+    baseOptions = {
+      title: {
+        text: '暂无数据',
+        textStyle: {
+          fontSize: 16,
+          fontWeight: 'normal',
+        },
+      },
+    }
+  }
+  console.log(cloneDeep(baseOptions))
+  chartInstance.value!.setOption(baseOptions)
+}
+
+watch(
+  () => props.loading,
+  (newState: boolean) => {
+    changeChartsLoading(newState)
+    if (newState === false) {
+      initChart()
+      initOptions()
+      console.log(props.data)
+    }
+
+    console.log(newState)
+  },
+  { deep: true },
+)
+
+watch(
+  () => props.legend,
+  newLegned => {
+    initOptions()
+    console.log(newLegned)
+  },
+  { deep: true },
+)
+</script>
+
+<template>
+  <div class="chart" ref="chartRef" style="width: 100%; height: 365px"></div>
+</template>
+
+<style scoped></style>

+ 1 - 1
src/components/echarts/TimeLineChart.vue

@@ -111,7 +111,7 @@ const initOptions = () => {
     name: '今日新增',
     data: [10, 22, 28, 43, 49],
     type: 'line',
-    smooth: true,
+    smooth: false,
   }
 
   linechart.value.clear()

+ 60 - 0
src/components/form/CSelect.vue

@@ -0,0 +1,60 @@
+<script setup lang="ts">
+import { CSelectType } from '@/types/HomeTypes'
+import type { CSelectItem } from '@/types/HomeTypes'
+
+interface Props {
+  selectInfo: {
+    [key: string]: CSelectItem
+  }
+  selectStyle?: string
+}
+withDefaults(defineProps<Props>(), {
+  selectStyle: 'width: 150px; margin-right: 10px',
+})
+</script>
+
+<template>
+  <div style="display: flex; align-items: center">
+    <template v-for="selectItem in selectInfo">
+      <div style="display: inline-flex; align-items: center">
+        <div
+          class="legendColor"
+          v-if="selectItem.type === CSelectType.RadioLegend"
+          :style="{ backgroundColor: selectItem.color }"
+        ></div>
+        <el-select
+          v-model="selectItem.value"
+          placeholder="Select"
+          v-bind="$attrs"
+          :multiple="
+            selectItem.type === CSelectType.Multiple ||
+            selectItem.type === CSelectType.MultipleTag
+          "
+          collapse-tags
+          :style="selectStyle"
+        >
+          <el-option
+            v-for="listItem in selectItem.options"
+            :key="listItem.value"
+            :label="listItem.label"
+            :value="listItem.value"
+          />
+          <template #tag v-if="selectItem.type === CSelectType.MultipleTag">
+            <span style="font-size: 14px; color: #606266; padding-left: 5px">{{
+              selectItem.tagText
+            }}</span>
+          </template>
+        </el-select>
+      </div>
+    </template>
+  </div>
+</template>
+
+<style scoped>
+.legendColor {
+  width: 20px;
+  height: 15px;
+  margin-right: 8px;
+  border-radius: 3px;
+}
+</style>

+ 199 - 0
src/hooks/HomeSelect/useAnalysisSelect.ts

@@ -0,0 +1,199 @@
+import { CSelectType } from '@/types/HomeTypes'
+import type {
+  BaseOption,
+  DateOption,
+  CSelectInfo,
+  CSelectRadio,
+  CSelectDate,
+  CSelectLegend,
+  CSelectMutipleTag,
+} from '@/types/HomeTypes'
+import { reactive } from 'vue'
+
+export function useAnalysisSelect() {
+  //  总览数据的选择框的信息格式
+  interface AnalysisSelectInfo extends CSelectInfo {
+    mediaSelect: CSelectRadio
+    dateSelect: CSelectDate
+    customIndicatorSelect: CSelectRadio
+  }
+
+  // 图例信息格式
+  interface LegendSelectInfo extends CSelectInfo {
+    leftLegned: CSelectLegend
+    rightLegned: CSelectLegend
+  }
+  // 左侧工具栏选择信息格式
+  interface LeftToolsSelectInfo extends CSelectInfo {
+    dataSource: CSelectRadio
+  }
+
+  // 右侧工具栏选择信息格式
+  interface RightToolsSelectInfo extends CSelectInfo {
+    dataCategory: CSelectRadio
+  }
+
+  // 媒体选择选项
+  const mediaSelectOptions = reactive<Array<BaseOption>>([
+    {
+      label: '全部媒体',
+      value: 'all',
+    },
+    {
+      label: '全部媒体',
+      value: 'all',
+    },
+  ])
+
+  // 日期选择
+  const dateSelectOptions = reactive<Array<DateOption>>([
+    {
+      label: '今天',
+      value: new Date(),
+    },
+    {
+      label: '昨天',
+      value: new Date(),
+    },
+  ])
+
+  // 项目选择
+  const projSelectOptions = reactive<Array<BaseOption>>([
+    {
+      label: '测试1',
+      value: 'ce1',
+    },
+    {
+      label: '测试2',
+      value: 'ce2',
+    },
+    {
+      label: '测试3',
+      value: 'ce3',
+    },
+    {
+      label: '测试4',
+      value: 'ce4',
+    },
+    {
+      label: '测试5',
+      value: 'ce5',
+    },
+    {
+      label: '测试6',
+      value: 'ce6',
+    },
+  ])
+
+  // 广告数据选择栏数据
+  const analysisSelectInfo = reactive<AnalysisSelectInfo>({
+    mediaSelect: {
+      type: CSelectType.Radio,
+      name: 'media',
+      value: mediaSelectOptions[0].value,
+      options: mediaSelectOptions,
+    },
+    dateSelect: {
+      type: CSelectType.Radio,
+      name: 'date',
+      value: dateSelectOptions[0].value,
+      options: dateSelectOptions,
+    },
+    customIndicatorSelect: {
+      tagText: '全部项目',
+      type: CSelectType.Radio,
+      name: 'project',
+      value: projSelectOptions[0].value,
+      options: projSelectOptions,
+    },
+  })
+
+  //   左边图例的选项
+  const leftLegnedOptions = reactive<Array<BaseOption>>([
+    {
+      label: '消耗',
+      value: 'cost',
+    },
+    {
+      label: '展示数',
+      value: 'show_count',
+    },
+  ])
+
+  // 右边图例选项
+  const rightLegnedOptions = reactive<Array<BaseOption>>([
+    {
+      label: '支付数',
+      value: 'pay_count',
+    },
+    {
+      label: '转化率',
+      value: 'convert_rate',
+    },
+  ])
+
+  // 图例的选择框信息
+  const legendSelectInfo = reactive<LegendSelectInfo>({
+    leftLegned: {
+      type: CSelectType.RadioLegend,
+      name: 'leftLegned',
+      value: leftLegnedOptions[0].value,
+      options: leftLegnedOptions,
+      color: '#bfdaff',
+    },
+    rightLegned: {
+      type: CSelectType.RadioLegend,
+      name: 'rightLegned',
+      value: rightLegnedOptions[1].value,
+      options: rightLegnedOptions,
+      color: '#f9b65d',
+    },
+  })
+
+  // 数据来源选项
+  const dataSourceOptions = reactive<Array<BaseOption>>([
+    {
+      label: '消耗',
+      value: 'consume',
+    },
+  ])
+
+  // 左侧工具栏选择框信息
+  const leftToolsSelectInfo = reactive<LeftToolsSelectInfo>({
+    dataSource: {
+      type: CSelectType.Radio,
+      name: 'dataSource',
+      value: dataSourceOptions[0].value,
+      options: dataSourceOptions,
+    },
+  })
+
+  //  数据分类选项
+  const categoryOptions = reactive<Array<BaseOption>>([
+    {
+      label: '汇总',
+      value: 'all',
+    },
+    {
+      label: 'Top5产品',
+      value: 'top5',
+    },
+  ])
+
+  //   右侧工具栏选择框信息
+  const rightToolsSelectInfo = reactive<RightToolsSelectInfo>({
+    dataCategory: {
+      type: CSelectType.Radio,
+      name: 'dataCategory',
+      value: categoryOptions[0].value,
+      options: categoryOptions,
+    },
+  })
+
+  return {
+    analysisSelectInfo,
+    legendSelectInfo,
+    leftToolsSelectInfo,
+    rightToolsSelectInfo,
+  }
+}

+ 20 - 0
src/hooks/HomeSelect/useHomeSelect.ts

@@ -0,0 +1,20 @@
+import { useOverviewSelect } from './useOverviewSelect'
+import { useAnalysisSelect } from './useAnalysisSelect'
+
+const { overviewSelectInfo } = useOverviewSelect()
+const {
+  analysisSelectInfo,
+  legendSelectInfo,
+  leftToolsSelectInfo,
+  rightToolsSelectInfo,
+} = useAnalysisSelect()
+
+export function useHomeSelect() {
+  return {
+    overviewSelectInfo,
+    analysisSelectInfo,
+    legendSelectInfo,
+    leftToolsSelectInfo,
+    rightToolsSelectInfo,
+  }
+}

+ 94 - 0
src/hooks/HomeSelect/useOverviewSelect.ts

@@ -0,0 +1,94 @@
+import { CSelectType } from '@/types/HomeTypes'
+import type {
+  BaseOption,
+  DateOption,
+  CSelectInfo,
+  CSelectRadio,
+  CSelectDate,
+  CSelectMutipleTag,
+} from '@/types/HomeTypes'
+import { reactive } from 'vue'
+
+export function useOverviewSelect() {
+  //  总览数据的选择框的信息格式
+  interface OverviewSelectInfo extends CSelectInfo {
+    mediaSelect: CSelectRadio
+    dateSelect: CSelectDate
+    customIndicatorSelect: CSelectMutipleTag
+  }
+
+  // 媒体选择选项
+  const mediaSelectOptions = reactive<Array<BaseOption>>([
+    {
+      label: '全部媒体',
+      value: 'all',
+    },
+    {
+      label: '全部媒体',
+      value: 'all',
+    },
+  ])
+
+  // 日期选择
+  const dateSelectOptions = reactive<Array<DateOption>>([
+    {
+      label: '今天',
+      value: new Date(),
+    },
+  ])
+
+  // 自定义指标选择
+  const indicatorSelectOptions = reactive<Array<BaseOption>>([
+    {
+      label: '测试1',
+      value: 'ce1',
+    },
+    {
+      label: '测试2',
+      value: 'ce2',
+    },
+    {
+      label: '测试3',
+      value: 'ce3',
+    },
+    {
+      label: '测试4',
+      value: 'ce4',
+    },
+    {
+      label: '测试5',
+      value: 'ce5',
+    },
+    {
+      label: '测试6',
+      value: 'ce6',
+    },
+  ])
+
+  // 广告数据选择栏数据
+  const overviewSelectInfo = reactive<OverviewSelectInfo>({
+    mediaSelect: {
+      type: CSelectType.Radio,
+      name: 'media',
+      value: mediaSelectOptions[0].value,
+      options: mediaSelectOptions,
+    },
+    dateSelect: {
+      type: CSelectType.Radio,
+      name: 'date',
+      value: dateSelectOptions[0].value,
+      options: dateSelectOptions,
+    },
+    customIndicatorSelect: {
+      tagText: '自定义指标',
+      type: CSelectType.MultipleTag,
+      name: 'customIndicator',
+      value: indicatorSelectOptions.map(item => item.value),
+      options: indicatorSelectOptions,
+    },
+  })
+
+  return {
+    overviewSelectInfo,
+  }
+}

+ 2 - 1
src/hooks/useRequest.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 17:24:06
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-18 17:15:29
+ * @LastEditTime: 2024-10-22 16:57:39
  * @FilePath: \Quantity-Creation-Management-System\src\hooks\useRequest.ts
  * @Description:
  *
@@ -29,6 +29,7 @@ export function useRequest() {
     mockAdTTAcc: `http://127.0.0.1:8003/mock/ad/ttacc`,
     mockAdTTProj: `http://127.0.0.1:8003/mock/ad/ttproj`,
     mockAdTTAd: `http://127.0.0.1:8003/mock/ad/ttad`,
+    mockChart: `http://127.0.0.1:8003/mock/home/chart`,
   }
 
   /**

+ 3 - 2
src/hooks/useTable.ts

@@ -1,5 +1,6 @@
 import type { TableData, BaseFieldInfo } from '@/types/Tables/table'
 import type { BaseTableInfo } from '@/types/Tables/tablePageData'
+import type { ResponseInfo } from '@/types/axios'
 import type {
   BaseFieldItem,
   TableFields,
@@ -14,9 +15,9 @@ export function useTable() {
     config: Object = {},
   ): Promise<Array<TableData>> => {
     try {
-      const res = await axiosInstance.get(url, config)
+      const res = (await axiosInstance.get(url, config)) as ResponseInfo
 
-      if (res.status !== 0) throw new Error('请求失败')
+      if (res.code !== 0) throw new Error('请求失败')
       return res.data as TableData[]
     } catch {
       console.log('数据请求失败')

+ 73 - 10
src/types/HomeTypes/index.ts

@@ -1,35 +1,98 @@
 // 总览广告数据类型
 interface overviewAdvertisingData {
+  name: string
   title: string
   value: number
   rate: number
 }
 
+// 选择框类型
+enum CSelectType {
+  Radio = 'radio',
+  MultipleTag = 'multipleTag',
+  Multiple = 'multiple',
+  RadioLegend = 'radioLegend',
+}
+
 // 下拉框选项基础类型
-interface FilterSelect {
+interface CSelectOption {
   label: string
   value: any
 }
 
-// 媒体下拉框选项类型
-interface MediaSelect extends FilterSelect {
+// 基本下拉框选项类型
+interface BaseOption extends CSelectOption {
   value: string
 }
 
 // 日期下拉框选项类型
-interface DateSelect extends FilterSelect {
+interface DateOption extends CSelectOption {
+  value: Date
+}
+
+// 总览数据选择框格式
+interface CSelectItem {
+  name: string
+  value: any
+  type: CSelectType
+  tagText?: string // 展示在多选框的文字,保持不变
+  color?: string // 颜色,只在legend中存在
+  options: Array<CSelectOption>
+}
+
+// 基础选择
+interface CSelectRadio extends CSelectItem {
+  type: CSelectType.Radio
+  options: Array<BaseOption>
+  value: string
+}
+
+// 日期选择
+interface CSelectDate extends CSelectItem {
+  type: CSelectType.Radio
+  options: Array<DateOption>
   value: Date
 }
 
-// 自定义指标下拉框选项类型
-interface CustomIndicatorSelect extends FilterSelect {
+// 多选带
+interface CSelectMutiple extends CSelectItem {
+  type: CSelectType.Multiple
+  options: Array<BaseOption>
+  value: string[]
+}
+
+// 带有自定义tag的多选
+interface CSelectMutipleTag extends CSelectItem {
+  type: CSelectType.MultipleTag
+  tagText: string // 展示在多选框的文字,保持不变
+  options: Array<BaseOption>
+  value: string[]
+}
+
+interface CSelectLegend extends CSelectItem {
+  type: CSelectType.RadioLegend
+  options: Array<BaseOption>
+  color: string
   value: string
 }
 
+// 选择框信息的基本组织格式
+interface CSelectInfo {
+  [key: string]: CSelectItem
+}
+
+export { CSelectType }
+
 export type {
   overviewAdvertisingData,
-  FilterSelect,
-  MediaSelect,
-  DateSelect,
-  CustomIndicatorSelect,
+  CSelectOption,
+  BaseOption,
+  DateOption,
+  CSelectInfo,
+  CSelectItem,
+  CSelectRadio,
+  CSelectDate,
+  CSelectMutiple,
+  CSelectMutipleTag,
+  CSelectLegend,
 }

+ 1 - 2
src/types/axios.ts

@@ -1,8 +1,7 @@
 export interface ResponseInfo {
   code: number
   msg: string
-  data?: any
-  count?: number
+  data: any
 }
 
 export interface ErrorResInfo {

+ 25 - 0
src/types/echarts/homeAnalysisChart.ts

@@ -0,0 +1,25 @@
+interface homeAnalysisChartData {
+  stat_datetime: string // 日期时间字符串
+  active: string // 活跃状态
+  active_cost: string // 活跃成本
+  active_rate: string // 活跃率
+  click: string // 点击数
+  cost: string // 成本
+  cpc: string // 每次点击成本
+  cpm: string // 千次展示成本
+  ctr: string // 点击率
+  pay_cost: string // 支付成本
+  pay_count: string // 支付次数
+  pay_rate: string // 支付率
+  show_count: string // 展示次数
+  conversion_num: string // 转换次数
+  convert_cost: string // 每次转化成本
+  convert_rate: string // 转化率
+}
+
+interface LegendInfo {
+  value: string
+  color: string
+}
+
+export type { homeAnalysisChartData, LegendInfo }

+ 236 - 77
src/views/Home/Home.vue

@@ -1,89 +1,146 @@
 <script setup lang="ts">
+import type { overviewAdvertisingData } from '@/types/HomeTypes'
+import type { BaseMenu } from '@/types/Promotion/Menu'
 import type {
-  overviewAdvertisingData,
-  FilterSelect,
-  MediaSelect,
-  DateSelect,
-  CustomIndicatorSelect,
-} from '@/types/HomeTypes'
+  homeAnalysisChartData,
+  LegendInfo,
+} from '@/types/echarts/homeAnalysisChart'
 
-import { reactive } from 'vue'
+import { computed, reactive, ref, watch } from 'vue'
+import { useRequest } from '@/hooks/useRequest'
 
+import Menu from '@/components/navigation/Menu.vue'
+import CSelect from '@/components/form/CSelect.vue'
+import HomeAnalysisLine from '@/components/echarts/HomeAnalysisLine.vue'
 import '@/assets/css/statistic.css'
 
+import { useHomeSelect } from '@/hooks/HomeSelect/useHomeSelect'
+
+import axiosInstance from '@/utils/axios/axiosInstance'
+import type { ResponseInfo } from '@/types/axios'
+
+const { AllApi } = useRequest()
+
+const {
+  overviewSelectInfo,
+  analysisSelectInfo,
+  legendSelectInfo,
+  leftToolsSelectInfo,
+  rightToolsSelectInfo,
+} = useHomeSelect()
+
+// 广告数据
 const overviewAdvertisingData = reactive<Array<overviewAdvertisingData>>([
   {
-    title: '消耗(元)',
+    name: 'ce1',
+    title: '消耗(元)11',
     value: 98500.03,
     rate: 24,
   },
   {
-    title: '消耗(元)',
+    name: 'ce2',
+    title: '消耗(元)22',
     value: 98500.03,
     rate: 24,
   },
   {
-    title: '消耗(元)',
+    name: 'ce3',
+    title: '消耗(元)33',
     value: 98500.03,
     rate: 24,
   },
   {
-    title: '消耗(元)',
+    name: 'ce4',
+    title: '消耗(元)44',
     value: 98500.03,
     rate: 24,
   },
   {
-    title: '消耗(元)',
+    name: 'ce5',
+    title: '消耗(元)55',
     value: 98500.03,
     rate: 24,
   },
   {
-    title: '消耗(元)',
+    name: 'ce6',
+    title: '消耗(元)66',
     value: 98500.03,
     rate: 24,
   },
 ])
 
-const mediaSelectList = reactive<Array<MediaSelect>>([
+// 分析栏导航菜单
+const dataAnalysisMenuList = reactive<Array<BaseMenu>>([
   {
-    label: '全部媒体',
-    value: 'all',
+    name: 'projAnalysis',
+    title: '项目分析',
   },
-])
-
-const dateSelectList = reactive<Array<DateSelect>>([
   {
-    label: '今天',
-    value: new Date(),
+    name: 'productAnalysis',
+    title: '产品分析',
   },
 ])
 
-const customIndicatorSelectList = reactive<Array<CustomIndicatorSelect>>([
-  {
-    label: '自定义指标',
-    value: 'custom',
-  },
-])
+const analysisiMenuActive = ref<string>('projAnalysis')
 
-const overviewSelectInfo = reactive<{
-  [key: string]: {
-    selected: Date | string
-    list: Array<FilterSelect>
+/**
+ * @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
+})
+
+/**
+ * @description: 数据分析栏菜单切换
+ * @param {*} newMenu 新的菜单值
+ * @return {*}
+ */
+const analysisiMenuChange = (newMenu: string) => {
+  analysisiMenuActive.value = newMenu
+}
+
+const chartLoading = ref<boolean>(true)
+
+const chartData = reactive<Array<homeAnalysisChartData>>([])
+
+const getChartData = async () => {
+  try {
+    chartLoading.value = true
+    const res = (await axiosInstance.get(AllApi.mockChart)) as ResponseInfo
+    if (res.code !== 0) throw new Error('获取图表数据失败')
+    chartData.splice(0, chartData.length, ...res.data)
+  } catch (err) {
+    console.log(err)
+  } finally {
+    chartLoading.value = false
   }
-}>({
-  mediaSelect: {
-    selected: mediaSelectList[0].value,
-    list: mediaSelectList,
-  },
-  dateSelect: {
-    selected: dateSelectList[0].value,
-    list: dateSelectList,
-  },
-  customIndicatorSelect: {
-    selected: customIndicatorSelectList[0].value,
-    list: customIndicatorSelectList,
-  },
+}
+
+/**
+ * @description: 计算图例所需要的信息
+ * @return {*}
+ */
+const analysisLegendInfo = computed<Array<LegendInfo>>(() => {
+  let result: Array<LegendInfo> = []
+  for (let [_k, v] of Object.entries(legendSelectInfo)) {
+    result.push({
+      value: v.value,
+      color: v.color!,
+    })
+  }
+  return result
 })
+
+getChartData()
 </script>
 
 <template>
@@ -95,50 +152,95 @@ const overviewSelectInfo = reactive<{
           <span class="getDetail">查看详情</span>
         </div>
         <div class="overviewFilterBox">
-          <el-select
-            v-for="selectItem in overviewSelectInfo"
-            v-model="selectItem.selected"
-            placeholder="Select"
-            size="small"
-            style="width: 130px; margin-right: 10px"
-          >
-            <el-option
-              v-for="listItem in selectItem.list"
-              :key="listItem.value"
-              :label="listItem.label"
-              :value="listItem.value"
-            />
-          </el-select>
+          <CSelect
+            :multiple-limit="6"
+            size="default"
+            :select-info="overviewSelectInfo"
+          ></CSelect>
         </div>
       </div>
       <div class="dataOverview">
         <el-row :gutter="16">
-          <el-col :span="4" v-for="item in overviewAdvertisingData">
-            <div class="statistic-card" html>
-              <el-statistic :value="item.value" :precision="2">
-                <template #title>
-                  <div style="display: inline-flex; align-items: center">
-                    {{ item.title }}
+          <el-col :span="4" v-for="item in overviewDataSelected">
+            <template
+              v-if="
+                overviewSelectInfo.customIndicatorSelect.value.includes(
+                  item.name,
+                )
+              "
+            >
+              <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">
+                    <span>环比</span>
+                    <span class="green">
+                      {{ item.rate }}%
+                      <el-icon>
+                        <CaretTop />
+                      </el-icon>
+                    </span>
                   </div>
-                </template>
-              </el-statistic>
-              <div class="statistic-footer">
-                <div class="footer-item">
-                  <span>环比</span>
-                  <span class="green">
-                    {{ item.rate }}%
-                    <el-icon>
-                      <CaretTop />
-                    </el-icon>
-                  </span>
                 </div>
               </div>
-            </div>
+            </template>
           </el-col>
         </el-row>
       </div>
     </div>
-    <div class="advertisingDataAnalysis"></div>
+    <div class="advertisingDataAnalysis">
+      <div class="analysisHeader">
+        <div class="headerMeun">
+          <Menu
+            mode="horizontal"
+            default-active="projAnalysis"
+            :menu-list="dataAnalysisMenuList"
+            @active-change="analysisiMenuChange"
+          ></Menu>
+        </div>
+      </div>
+      <div class="analysisContent">
+        <div class="lineChartContainer">
+          <div class="chartBoxHeader">
+            <div class="layoutItem"></div>
+            <CSelect :select-info="analysisSelectInfo"></CSelect>
+          </div>
+          <div class="chartBoxTools">
+            <div
+              class="dataTools"
+              v-if="analysisiMenuActive !== 'projAnalysis'"
+            >
+              <div class="dataSource">
+                <CSelect :select-info="leftToolsSelectInfo"></CSelect>
+              </div>
+              <div class="dataCategory">
+                <CSelect :select-info="rightToolsSelectInfo"></CSelect>
+              </div>
+            </div>
+            <div class="legendTools" v-else>
+              <CSelect
+                :select-style="`width:100px;margin-right:15px;`"
+                size="small"
+                :select-info="legendSelectInfo"
+              ></CSelect>
+            </div>
+          </div>
+          <div class="chartContent">
+            <HomeAnalysisLine
+              :legend="analysisLegendInfo"
+              :data="chartData"
+              :loading="chartLoading"
+            ></HomeAnalysisLine>
+          </div>
+        </div>
+      </div>
+    </div>
     <div class="topArea"></div>
   </div>
 </template>
@@ -183,4 +285,61 @@ const overviewSelectInfo = reactive<{
 .dataOverview {
   width: 100%;
 }
+
+.advertisingDataAnalysis {
+  position: relative;
+  width: 85%;
+  margin: 0 auto;
+  padding: 16px 16px 24px;
+  background-color: #fff;
+  border-radius: 2px;
+  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
+}
+
+.analysisHeader {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 100%;
+  position: absolute;
+  top: 16px;
+  z-index: 500;
+}
+
+.headerMeun {
+  width: 50%;
+}
+
+.analysisContent {
+  width: 100%;
+  height: 500px;
+  position: relative;
+}
+
+.lineChartContainer {
+  width: 100%;
+  height: 100%;
+  padding: 16px 16px 0;
+}
+
+.chartBoxHeader {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.chartBoxTools {
+  margin-top: 24px;
+}
+
+.legendTools {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.dataTools {
+  display: flex;
+  justify-content: space-between;
+}
 </style>