Pārlūkot izejas kodu

feat: 新增底部图表

MTrun 4 gadi atpakaļ
vecāks
revīzija
310ffec00d

+ 1 - 0
src/components/echart/index.tsx

@@ -53,6 +53,7 @@ export default defineComponent({
     watch(
       () => props.options,
       val => {
+        console.log(val);
         val && initChart()
       },
       {

+ 150 - 0
src/views/bottomLeft/chart/draw.tsx

@@ -0,0 +1,150 @@
+import { defineComponent, watch, shallowReactive } from 'vue'
+import * as echarts from 'echarts'
+// 声明类型
+const PropsType = {
+  cdata: {
+    type: Object,
+    require: true
+  }
+} as const
+
+// 定义主体
+export default defineComponent({
+  props: PropsType,
+  setup(props) {
+    // 配置项
+    let options = shallowReactive({})
+
+    watch(
+      () => props.cdata,
+      (val: any) => {
+        options = {
+          tooltip: {
+            trigger: "axis",
+            backgroundColor: "rgba(255,255,255,0.1)",
+            axisPointer: {
+              type: "shadow",
+              label: {
+                show: true,
+                backgroundColor: "#7B7DDC"
+              }
+            }
+          },
+          legend: {
+            data: ["已贯通", "计划贯通", "贯通率"],
+            textStyle: {
+              color: "#B4B4B4"
+            },
+            top: "0%"
+          },
+          grid: {
+            x: "8%",
+            width: "88%",
+            y: "2%",
+            bottom: '8%'
+          },
+          xAxis: {
+            data: val.category,
+            axisLine: {
+              lineStyle: {
+                color: "#B4B4B4"
+              }
+            },
+            axisTick: {
+              show: false
+            }
+          },
+          yAxis: [
+            {
+              splitLine: { show: false },
+              axisLine: {
+                lineStyle: {
+                  color: "#B4B4B4"
+                }
+              },
+
+              axisLabel: {
+                formatter: "{value} "
+              }
+            },
+            {
+              splitLine: { show: false },
+              axisLine: {
+                lineStyle: {
+                  color: "#B4B4B4"
+                }
+              },
+              axisLabel: {
+                formatter: "{value} "
+              }
+            }
+          ],
+          series: [
+            {
+              name: "贯通率",
+              type: "line",
+              smooth: true,
+              showAllSymbol: true,
+              symbol: "emptyCircle",
+              symbolSize: 8,
+              yAxisIndex: 1,
+              itemStyle: {
+                normal: {
+                  color: "#F02FC2"
+                }
+              },
+              data: val.rateData
+            },
+            {
+              name: "已贯通",
+              type: "bar",
+              barWidth: 10,
+              itemStyle: {
+                normal: {
+                  barBorderRadius: 5,
+                  color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: "#956FD4" },
+                    { offset: 1, color: "#3EACE5" }
+                  ])
+                }
+              },
+              data: val.barData
+            },
+            {
+              name: "计划贯通",
+              type: "bar",
+              barGap: "-100%",
+              barWidth: 10,
+              itemStyle: {
+                normal: {
+                  barBorderRadius: 5,
+                  color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: "rgba(156,107,211,0.8)" },
+                    { offset: 0.2, color: "rgba(156,107,211,0.5)" },
+                    { offset: 1, color: "rgba(156,107,211,0.2)" }
+                  ])
+                }
+              },
+              z: -12,
+              data: val.lineData
+            }
+          ]
+        }
+      },
+      {
+        immediate: true,
+        deep: true
+      }
+    )
+
+    return () => {
+      const height = "450px"
+      const width = "100%"
+
+      return <div>
+        <echart options={options} height={height} width={width} />
+      </div>
+    }
+  }
+})
+

+ 137 - 0
src/views/bottomLeft/chart/index.tsx

@@ -0,0 +1,137 @@
+import { defineComponent, reactive, onMounted } from 'vue'
+import Draw from './draw'
+
+export default defineComponent({
+  components: {
+    Draw
+  },
+  setup() {
+    const cdata = reactive({
+      category: [
+        "市区",
+        "万州",
+        "江北",
+        "南岸",
+        "北碚",
+        "綦南",
+        "长寿",
+        "永川",
+        "璧山",
+        "江津",
+        "城口",
+        "大足",
+        "垫江",
+        "丰都",
+        "奉节",
+        "合川",
+        "江津区",
+        "开州",
+        "南川",
+        "彭水",
+        "黔江",
+        "石柱",
+        "铜梁",
+        "潼南",
+        "巫山",
+        "巫溪",
+        "武隆",
+        "秀山",
+        "酉阳",
+        "云阳",
+        "忠县",
+        "川东",
+        "检修"
+      ],
+      lineData: [
+        18092,
+        20728,
+        24045,
+        28348,
+        32808,
+        36097,
+        39867,
+        44715,
+        48444,
+        50415,
+        56061,
+        62677,
+        59521,
+        67560,
+        18092,
+        20728,
+        24045,
+        28348,
+        32808,
+        36097,
+        39867,
+        44715,
+        48444,
+        50415,
+        36097,
+        39867,
+        44715,
+        48444,
+        50415,
+        50061,
+        32677,
+        49521,
+        32808
+      ],
+      barData: [
+        4600,
+        5000,
+        5500,
+        6500,
+        7500,
+        8500,
+        9900,
+        12500,
+        14000,
+        21500,
+        23200,
+        24450,
+        25250,
+        33300,
+        4600,
+        5000,
+        5500,
+        6500,
+        7500,
+        8500,
+        9900,
+        22500,
+        14000,
+        21500,
+        8500,
+        9900,
+        12500,
+        14000,
+        21500,
+        23200,
+        24450,
+        25250,
+        7500
+      ],
+      rateData: []
+    })
+
+    // methods
+    const setData = () => {
+      for (let i = 0; i < cdata.barData.length - 1; i++) {
+        const rate = cdata.barData[i] / cdata.lineData[i];
+        cdata.rateData.push(rate.toFixed(2));
+      }
+    }
+
+    // 生命周期
+    onMounted(() => {
+      setData()
+    })
+
+    return () => {
+      return <div>
+        <Draw cdata={cdata} />
+      </div>
+    }
+  }
+})

+ 52 - 0
src/views/bottomLeft/index.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="bottomLeft">
+    <div class="bg-color-black">
+      <div class="d-flex pt-2 pl-2">
+        <span>
+          <i class="iconfont icon-chart-line" />
+        </span>
+        <div class="d-flex">
+          <span class="fs-xl text mx-2 mt-1">数据统计图</span>
+        </div>
+      </div>
+      <div>
+        <chart />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Chart from "./chart/index";
+export default {
+  components: {
+    Chart
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+$box-height: 520px;
+$box-width: 100%;
+.bottomLeft {
+  padding: 25px 16px;
+  height: $box-height;
+  width: $box-width;
+  border-radius: 5px;
+  .bg-color-black {
+    height: $box-height - 40px;
+    border-radius: 10px;
+  }
+  .text {
+    color: #c3cbde;
+  }
+  .chart-box {
+    margin-top: 16px;
+    width: 170px;
+    height: 170px;
+    .active-ring-name {
+      padding-top: 10px;
+    }
+  }
+}
+</style>

+ 359 - 0
src/views/bottomRight/chart/draw.tsx

@@ -0,0 +1,359 @@
+import { defineComponent, watch, reactive } from 'vue'
+// 声明类型
+const PropsType = {
+  cdata: {
+    type: Object,
+    require: true
+  }
+} as const
+
+// 定义主体
+export default defineComponent({
+  props: PropsType,
+  setup(props) {
+    // 定义颜色
+    const colorList = {
+      linearYtoG: {
+        type: "linear",
+        x: 0,
+        y: 0,
+        x2: 1,
+        y2: 1,
+        colorStops: [
+          {
+            offset: 0,
+            color: "#f5b44d"
+          },
+          {
+            offset: 1,
+            color: "#28f8de"
+          }
+        ]
+      },
+      linearGtoB: {
+        type: "linear",
+        x: 0,
+        y: 0,
+        x2: 1,
+        y2: 0,
+        colorStops: [
+          {
+            offset: 0,
+            color: "#43dfa2"
+          },
+          {
+            offset: 1,
+            color: "#28f8de"
+          }
+        ]
+      },
+      linearBtoG: {
+        type: "linear",
+        x: 0,
+        y: 0,
+        x2: 1,
+        y2: 0,
+        colorStops: [
+          {
+            offset: 0,
+            color: "#1c98e8"
+          },
+          {
+            offset: 1,
+            color: "#28f8de"
+          }
+        ]
+      },
+      areaBtoG: {
+        type: "linear",
+        x: 0,
+        y: 0,
+        x2: 0,
+        y2: 1,
+        colorStops: [
+          {
+            offset: 0,
+            color: "rgba(35,184,210,.2)"
+          },
+          {
+            offset: 1,
+            color: "rgba(35,184,210,0)"
+          }
+        ]
+      }
+    }
+    // 配置项
+    let options = reactive({})
+
+    watch(
+      () => props.cdata,
+      (val: any) => {
+        console.log('触发');
+        options = {
+          title: {
+            text: "",
+            textStyle: {
+              color: "#D3D6DD",
+              fontSize: 24,
+              fontWeight: "normal"
+            },
+            subtext: val.year + "/" + val.weekCategory[6],
+            subtextStyle: {
+              color: "#fff",
+              fontSize: 16
+            },
+            top: 50,
+            left: 80
+          },
+          legend: {
+            top: 120,
+            left: 80,
+            orient: "vertical",
+            itemGap: 15,
+            itemWidth: 12,
+            itemHeight: 12,
+            data: ["平均指标", "我的指标"],
+            textStyle: {
+              color: "#fff",
+              fontSize: 14
+            }
+          },
+          tooltip: {
+            trigger: "item"
+          },
+          radar: {
+            center: ["68%", "27%"],
+            radius: "40%",
+            name: {
+              color: "#fff"
+            },
+            splitNumber: 8,
+            axisLine: {
+              lineStyle: {
+                color: colorList.linearYtoG,
+                opacity: 0.6
+              }
+            },
+            splitLine: {
+              lineStyle: {
+                color: colorList.linearYtoG,
+                opacity: 0.6
+              }
+            },
+            splitArea: {
+              areaStyle: {
+                color: "#fff",
+                opacity: 0.1,
+                shadowBlur: 25,
+                shadowColor: "#000",
+                shadowOffsetX: 0,
+                shadowOffsetY: 5
+              }
+            },
+            indicator: [
+              {
+                name: "服务态度",
+                max: val.maxData
+              },
+              {
+                name: "产品质量",
+                max: 10
+              },
+              {
+                name: "任务效率",
+                max: 12
+              },
+              {
+                name: "售后保障",
+                max: 3.5
+              }
+            ]
+          },
+          grid: {
+            left: 90,
+            right: 80,
+            bottom: 40,
+            top: "60%"
+          },
+          xAxis: {
+            type: "category",
+            position: "bottom",
+            axisLine: true,
+            axisLabel: {
+              color: "rgba(255,255,255,.8)",
+              fontSize: 12
+            },
+            data: val.weekCategory
+          },
+          // 下方Y轴
+          yAxis: {
+            name: "工单",
+            nameLocation: "end",
+            nameGap: 24,
+            nameTextStyle: {
+              color: "rgba(255,255,255,.5)",
+              fontSize: 14
+            },
+            max: val.maxData,
+            splitNumber: 4,
+
+            axisLine: {
+              lineStyle: {
+                opacity: 0
+              }
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: "#fff",
+                opacity: 0.1
+              }
+            },
+            axisLabel: {
+              color: "rgba(255,255,255,.8)",
+              fontSize: 12
+            }
+          },
+          series: [
+            {
+              name: "",
+              type: "radar",
+              symbolSize: 0,
+              data: [
+                {
+                  value: val.radarDataAvg[6],
+                  name: "平均指标",
+                  itemStyle: {
+                    normal: {
+                      color: "#f8d351"
+                    }
+                  },
+                  lineStyle: {
+                    normal: {
+                      opacity: 0
+                    }
+                  },
+                  areaStyle: {
+                    normal: {
+                      color: "#f8d351",
+                      shadowBlur: 25,
+                      shadowColor: "rgba(248,211,81,.3)",
+                      shadowOffsetX: 0,
+                      shadowOffsetY: -10,
+                      opacity: 1
+                    }
+                  }
+                },
+                {
+                  value: val.radarData[6],
+                  name: "我的指标",
+                  itemStyle: {
+                    normal: {
+                      color: "#43dfa2"
+                    }
+                  },
+                  lineStyle: {
+                    normal: {
+                      opacity: 0
+                    }
+                  },
+                  areaStyle: {
+                    normal: {
+                      color: colorList.linearGtoB,
+                      shadowBlur: 15,
+                      shadowColor: "rgba(0,0,0,.2)",
+                      shadowOffsetX: 0,
+                      shadowOffsetY: 5,
+                      opacity: 0.8
+                    }
+                  }
+                }
+              ]
+            },
+            {
+              name: "",
+              type: "line",
+              smooth: true,
+              symbol: "emptyCircle",
+              symbolSize: 8,
+              itemStyle: {
+                normal: {
+                  color: "#fff"
+                }
+              },
+              lineStyle: {
+                normal: {
+                  color: colorList.linearBtoG,
+                  width: 3
+                }
+              },
+              areaStyle: {
+                normal: {
+                  color: colorList.areaBtoG
+                }
+              },
+              data: val.weekLineData,
+              lineSmooth: true,
+              markLine: {
+                silent: true,
+                data: [
+                  {
+                    type: "average",
+                    name: "平均值"
+                  }
+                ],
+                precision: 0,
+                label: {
+                  normal: {
+                    formatter: "平均值: \n {c}"
+                  }
+                },
+                lineStyle: {
+                  normal: {
+                    color: "rgba(248,211,81,.7)"
+                  }
+                }
+              },
+              tooltip: {
+                position: "top",
+                formatter: "{c} m",
+                backgroundColor: "rgba(28,152,232,.2)",
+                padding: 6
+              }
+            },
+            {
+              name: "占位背景",
+              type: "bar",
+              itemStyle: {
+                normal: {
+                  show: true,
+                  color: "#000",
+                  opacity: 0
+                }
+              },
+              silent: true,
+              barWidth: "50%",
+              data: val.weekMaxData,
+              animation: false
+            }
+          ]
+        }
+        options = JSON.parse(JSON.stringify(options))
+      },
+      {
+        immediate: true,
+        deep: true
+      }
+    )
+
+    return () => {
+      const height = "480px"
+      const width = "100%"
+
+      return <div>
+        <echart options={options} height={height} width={width} />
+      </div>
+    }
+  }
+})
+

+ 85 - 0
src/views/bottomRight/chart/index.tsx

@@ -0,0 +1,85 @@
+import { defineComponent, reactive, onMounted, ref } from 'vue';
+import Draw from './draw'
+
+export default defineComponent({
+  components: {
+    Draw
+  },
+  setup() {
+    const drawTiming = ref(0)
+    const cdata = reactive({
+      year: null,
+      weekCategory: [],
+      radarData: [],
+      radarDataAvg: [],
+      maxData: 12000,
+      weekMaxData: [],
+      weekLineData: []
+    })
+
+    // methods
+    const setData = () => {
+      // 清空轮询数据
+      cdata.weekCategory = [];
+      cdata.weekMaxData = [];
+      cdata.weekLineData = [];
+      cdata.radarData = [];
+      cdata.radarDataAvg = [];
+
+      const dateBase = new Date();
+      cdata.year = dateBase.getFullYear();
+      // 周数据
+      for (let i = 0; i < 7; i++) {
+        // 日期
+        const date = new Date();
+        cdata.weekCategory.unshift([date.getMonth() + 1, date.getDate() - i].join("/"));
+
+        // 折线图数据
+        cdata.weekMaxData.push(cdata.maxData);
+        const distance = Math.round(Math.random() * 11000 + 500);
+        cdata.weekLineData.push(distance);
+
+        // 雷达图数据
+        // 我的指标
+        const averageSpeed = +(Math.random() * 5 + 3).toFixed(3);
+        const maxSpeed = averageSpeed + +(Math.random() * 3).toFixed(2);
+        const hour = +(distance / 1000 / averageSpeed).toFixed(1);
+        const radarDayData = [distance, averageSpeed, maxSpeed, hour];
+        cdata.radarData.unshift(radarDayData);
+
+        // 平均指标
+        const distanceAvg = Math.round(Math.random() * 8000 + 4000);
+        const averageSpeedAvg = +(Math.random() * 4 + 4).toFixed(3);
+        const maxSpeedAvg = averageSpeedAvg + +(Math.random() * 2).toFixed(2);
+        const hourAvg = +(distance / 1000 / averageSpeed).toFixed(1);
+        const radarDayDataAvg = [
+          distanceAvg,
+          averageSpeedAvg,
+          maxSpeedAvg,
+          hourAvg
+        ];
+        cdata.radarDataAvg.unshift(radarDayDataAvg);
+      }
+
+    }
+
+    // 定时函数
+    const drawTimingFn = () => {
+      setData();
+      drawTiming.value = setInterval(() => {
+        setData();
+      }, 6000);
+    }
+
+    // 生命周期
+    onMounted(() => {
+      drawTimingFn()
+    })
+
+    return () => {
+      return <div>
+        <Draw cdata={cdata} />
+      </div>
+    }
+  }
+})

+ 52 - 0
src/views/bottomRight/index.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="bottomRight">
+    <div class="bg-color-black">
+      <div class="d-flex pt-2 pl-2">
+        <span>
+          <i class="iconfont icon-chart-area" />
+        </span>
+        <div class="d-flex">
+          <span class="fs-xl text mx-2 mt-1">数据统计图</span>
+        </div>
+      </div>
+      <div>
+        <chart />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Chart from "./chart/index";
+export default {
+  components: {
+    Chart
+  }
+}
+</script>
+
+<style lang="scss" class>
+$box-height: 520px;
+$box-width: 100%;
+.bottomRight {
+  padding: 14px 16px;
+  height: $box-height;
+  width: $box-width;
+  border-radius: 5px;
+  .bg-color-black {
+    height: $box-height - 30px;
+    border-radius: 10px;
+  }
+  .text {
+    color: #c3cbde;
+  }
+  .chart-box {
+    margin-top: 16px;
+    width: 170px;
+    height: 170px;
+    .active-ring-name {
+      padding-top: 10px;
+    }
+  }
+}
+</style>

+ 1 - 4
src/views/centerLeft1/chart/draw.tsx

@@ -4,10 +4,7 @@ import { defineComponent, watch, shallowReactive } from 'vue'
 const PropsType = {
   cdata: {
     type: Object,
-    default: () => ({
-      xData: [],
-      seriesData: []
-    })
+    require: true
   }
 } as const
 

+ 1 - 1
src/views/centerLeft2/chart/draw.tsx

@@ -4,7 +4,7 @@ import { defineComponent, watch, shallowReactive, nextTick, ref, onUnmounted } f
 const PropsType = {
   cdata: {
     type: Array,
-    default: () => [],
+    require: true
   }
 } as const
 

+ 1 - 1
src/views/centerLeft2/index.vue

@@ -27,7 +27,7 @@ export default defineComponent({
 })
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 .centreLeft1 {
   $box-width: 300px;
   $box-height: 410px;

+ 1 - 1
src/views/centerRight1/index.vue

@@ -53,7 +53,7 @@ export default {
 }
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 $box-height: 400px;
 $box-width: 340px;
 .centerRight1 {

+ 1 - 1
src/views/centerRight2/index.vue

@@ -48,7 +48,7 @@ export default {
 }
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 $box-height: 410px;
 $box-width: 300px;
 .centerRight2 {

+ 8 - 4
src/views/index/index.vue

@@ -80,10 +80,10 @@
           <!-- 第四行数据 -->
           <div class="bototm-box">
             <dv-border-box-13>
-              <!-- <bottomLeft /> -->
+              <bottom-left />
             </dv-border-box-13>
             <dv-border-box-12>
-              <!-- <bottomRight /> -->
+              <bottom-right />
             </dv-border-box-12>
           </div>
         </div>
@@ -100,9 +100,11 @@ import useIndex from '@/utils/useDraw'
 import { title, subtitle, moduleInfo } from '@/constant/index'
 import CenterLeft1 from "../centerLeft1/index.vue";
 import CenterLeft2 from "../centerLeft2/index.vue";
+import Center from "../center/index.vue";
 import CenterRight1 from "../centerRight1/index.vue";
 import CenterRight2 from "../centerRight2/index.vue";
-import Center from "../center/index.vue";
+import BottomLeft from "../bottomLeft/index.vue";
+import BottomRight from "../bottomRight/index.vue";
 
 export default defineComponent({
   components: {
@@ -110,7 +112,9 @@ export default defineComponent({
     CenterLeft2,
     Center,
     CenterRight1,
-    CenterRight2
+    CenterRight2,
+    BottomLeft,
+    BottomRight
   },
   setup() {
     // * 加载标识