Procházet zdrojové kódy

feat: 新增echart

whh před 9 měsíci
rodič
revize
a38a9dbb9c
3 změnil soubory, kde provedl 270 přidání a 113 odebrání
  1. 229 55
      src/utils/echartOptions.js
  2. 6 0
      src/utils/format.js
  3. 35 58
      src/views/analyse/ForecastView.vue

+ 229 - 55
src/utils/echartOptions.js

@@ -2,22 +2,162 @@ import * as echarts from 'echarts';
 let xLabel = [11, 12, 13, 14, 15, 16, 17, 18, 19]
 let goToSchool = [9.019096, 17.795139, 6.467014, 5.746528, 10.16493, 10.112847, 7.75, 6.74, 7.14]
 
+export const getAreaOptions = ({ xAxisData, seriesList }) => {
+  const series = seriesList.map((data, index) => {
+    const i = !index;
+    return {
+      name: i ? '过去' : '未来',
+      type: 'line',
+      symbol: 'circle',
+      showAllSymbol: true,
+      symbolSize: 5,
+      smooth: true,
+      lineStyle: {
+        normal: {
+          width: 2,
+          color: i ? "rgba(25,163,223,1)" : "rgba(36,175,83,1)", // 线条颜色
+        },
+        borderColor: 'rgba(0,0,0,.4)',
+      },
+      itemStyle: {
+        color: i ? "#b7f9ff" : "#fff",
+        borderColor: i ? "#2185da" : "#2ee055",
+        borderWidth: 1,
+        shadowColor: 'rgba(22, 137, 229)',
+        shadowBlur: 1
+      },
+      areaStyle: {
+        normal: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+            offset: 0,
+            color: i ? "rgba(25,163,223,.3)" : "rgba(48, 209, 136,.3)"
+          },
+          {
+            offset: 1,
+            color: i ? "rgba(25,163,223, 0)" : "rgba(48, 209, 136, 0)"
+          }
+          ], false),
+          shadowColor: 'rgba(25,163,223, 0.5)',
+          shadowBlur: 20
+        }
+      },
+      z: i ? 3 : 2,
+      data
+    }
+  })
+
+  return {
+    backgroundColor: '#fff',
+    tooltip: {
+      trigger: "axis",
+      show: true,
+      formatter: function (params) {
+        const [item] = params.filter(item => item.value);
+        const color = item.dataIndex <= 5 ? '#2185da' : '#2ee055'
+        return `
+          <div class="text-[12px]">
+            <p>时间:${item.name + ':00'}</p>
+            <p class="flex items-center space-x-[6px]">
+              <span class="block w-[6px] h-[6px] rounded-full bg-[${color}]"></span>
+              <span>${Number(item.value.toFixed(2))} mg/L</span>
+            </p>
+          </div>
+          `
+      },
+    },
+    grid: {
+      top: '10%',
+      left: 40,
+      right: '5%',
+      bottom: '15%',
+    },
+    xAxis: [{
+      type: 'category',
+      boundaryGap: false,
+      axisLine: {
+        show: true,
+        lineStyle: {
+          color: '#e0e6f1'
+        },
+      },
+      axisLabel: {
+        textStyle: {
+          color: '#1F2328',
+          fontSize: 12,
+        },
+        formatter: function (data) {
+          return data + ":00"
+        }
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          type: 'dashed',
+        },
+      },
+      axisTick: {
+        show: false,
+      },
+      data: xLabel
+    }],
+    yAxis: [{
+      name: '',
+      nameTextStyle: {
+        fontSize: 12,
+        align: 'right',
+        padding: [10, 5],
+      },
+      min: 0,
+      splitLine: {
+        show: true,
+        lineStyle: {
+          type: 'dashed',
+        },
+      },
+      axisLine: {
+        show: false,
+        lineStyle: {
+          color: "#233653"
+        }
+      },
+      axisLabel: {
+        show: true,
+        textStyle: {
+          color: '#1F2328',
+          // align: 'right',
+          padding: 0
+        },
+        formatter: function (value) {
+          if (value === 0) {
+            return value
+          }
+          return value
+        }
+      },
+      axisTick: {
+        show: false,
+      },
+    }],
+    series
+  }
+}
+
 export const areaOptions = {
   backgroundColor: '#fff',
   tooltip: {
     trigger: "axis",
-    // backgroundColor: "#202630",
-    // borderColor: "#202630",
-    // textStyle: {
-    //   color: "#fff",
-    //   fontSize: 12,
-    // },
-    // axisPointer: {
-    //   type: "line",
-    //   lineStyle: {
-    //     type: "solid",
-    //   },
-    // },
+    backgroundColor: "#202630",
+    borderColor: "#202630",
+    textStyle: {
+      color: "#fff",
+      fontSize: 12,
+    },
+    axisPointer: {
+      type: "line",
+      lineStyle: {
+        type: "solid",
+      },
+    },
     formatter: function (params) {
       return params[0].name + 'asda' + ':<br/>' + params[0].value + '万';
     },
@@ -104,7 +244,7 @@ export const areaOptions = {
         if (value === 0) {
           return value
         }
-        return value 
+        return value
       }
     },
     axisTick: {
@@ -113,51 +253,85 @@ export const areaOptions = {
   }],
   series: [
     {
-    name: '上学',
-    type: 'line',
-    symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆
-    showAllSymbol: true,
-    symbolSize: 5,
-    smooth: true,
-    lineStyle: {
-      normal: {
-        width: 2,
-        color: "rgba(25,163,223,1)", // 线条颜色
-      },
-      borderColor: 'rgba(0,0,0,.4)',
-    },
-    itemStyle: {
-      color: "#b7f9ff",
-      borderColor: "#2185da",
-      borderWidth: 1,
-      shadowColor: 'rgba(22, 137, 229)',
-      shadowBlur: 1
-    },
-    tooltip: {
-      show: true,
-      valueFormatter: function (value) {
-        return value + '元';
+      name: '上学',
+      type: 'line',
+      symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆
+      showAllSymbol: true,
+      symbolSize: 5,
+      smooth: true,
+      lineStyle: {
+        normal: {
+          width: 2,
+          color: "rgba(25,163,223,1)", // 线条颜色
+        },
+        borderColor: 'rgba(0,0,0,.4)',
       },
+      itemStyle: {
+        color: "#b7f9ff",
+        borderColor: "#2185da",
+        borderWidth: 1,
+        shadowColor: 'rgba(22, 137, 229)',
+        shadowBlur: 1
+      },
+      areaStyle: { //区域填充样式
+        normal: {
+          //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+            offset: 0,
+            color: "rgba(25,163,223,.3)"
+          },
+          {
+            offset: 1,
+            color: "rgba(25,163,223, 0)"
+          }
+          ], false),
+          shadowColor: 'rgba(25,163,223, 0.5)', //阴影颜色
+          shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
+        }
+      },
+      z: 3,
+      data: [9.019096, 17.795139, 6.467014, 5.746528, 10.16493, 10.112847, null, null, null]
     },
-    areaStyle: { //区域填充样式
-      normal: {
-        //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
-        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-          offset: 0,
-          color: "rgba(25,163,223,.3)"
+    {
+      name: '2222222',
+      type: 'line',
+      symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆
+      showAllSymbol: true,
+      symbolSize: 5,
+      smooth: true,
+      lineStyle: {
+        normal: {
+          width: 2,
+          color: "rgba(36,175,83,1)", // 线条颜色
         },
-        {
-          offset: 1,
-          color: "rgba(25,163,223, 0)"
+        borderColor: 'rgba(0,0,0,.4)',
+      },
+      itemStyle: {
+        color: "#fff",
+        borderColor: "#2ee055",
+        borderWidth: 1,
+        shadowColor: 'rgba(22, 137, 229)',
+        shadowBlur: 1
+      },
+      areaStyle: { //区域填充样式
+        normal: {
+          //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+            offset: 0,
+            color: "rgba(48, 209, 136,.3)"
+          },
+          {
+            offset: 1,
+            color: "rgba(48, 209, 136, 0)"
+          }
+          ], false),
+          shadowColor: 'rgba(25,163,223, 0.5)', //阴影颜色
+          shadowBlur: 20
         }
-        ], false),
-        shadowColor: 'rgba(25,163,223, 0.5)', //阴影颜色
-        shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
-      }
-    },
-    data: goToSchool
-  },
-  
-]
+      },
+      z: 2,
+      data: [null, null, null, null, null, 10.112847, 7.75, 6.74, 7.14]
+    }
+  ]
 };
 

+ 6 - 0
src/utils/format.js

@@ -40,3 +40,9 @@ export const format = {
 export const truncateDecimals = num => {
   return Number((Math.floor(num * 100) / 100).toFixed(2));
 }
+
+
+export const replaceArray = (array, startIndex, length, replacementValue) => {
+  array.splice(startIndex, length, ...Array(length).fill(replacementValue));
+  return array;
+}

+ 35 - 58
src/views/analyse/ForecastView.vue

@@ -4,12 +4,12 @@ import { useRouter } from 'vue-router';
 import { NTabs, NTab } from 'naive-ui';
 // import * as G2Plot from '@antv/g2plot';
 import * as echarts from 'echarts';
-import { areaOptions } from '@/utils/echartOptions'
+import { getAreaOptions, areaOptions } from '@/utils/echartOptions'
 // import { Area } from '@antv/g2plot';
 import { useChatStore } from '@/stores/modules/chatStore';
 import { BaseTable, ChatWelcome, RecodeSquareCardItem, TheSubMenu, TheChatView } from "@/components";
 import { ChatBaseCard, ChatAnswer } from '@/components/Chat';
-import { formatToData } from "@/utils/format";
+import { formatToData, replaceArray } from "@/utils/format";
 import { waterApi } from '@/api/water';
 import { useInfinite, useRecommend, useScroll } from '@/composables'
 import { columns } from './config';
@@ -23,8 +23,9 @@ const chatStore = useChatStore();
 
 const answerResult = ref("");
 const textDataSources = ref(null);
+const chartTitle = ref("");
 
-const chart = ref({});
+let chart = {};
 const echartRef = ref({});
 
 // 进出水数据
@@ -42,66 +43,34 @@ const onChangeTabs = warningStatus => {
 const handleOpenContent = async ({ id, reason: title }) => {
   const { data } = await waterApi.getWaringDetails(id);
   const showVal = JSON.parse(data.showVal);
-  const { basic, jsData, csData, chartsData } = showVal;
-  console.log(chartsData);
+  const { basic, jsData, csData, chartsData, chartsTitle } = showVal;
+
   answerResult.value = data.answer;
 
+  chartTitle.value = chartsTitle;
+
   basic.title = title
   textDataSources.value = formatToData(basic, '预测值');
 
   jsTableData.value = [jsData];
   csTableData.value = [csData];
 
-
+  createLineChat(chartsData);
   scrollToTop();
 }
 
 // 创建图表
-const initLineChat = () => {
-  // 准备数据
-  const data =
-    [
-      {
-        "time": "13",
-        "val": 11.063026
-      },
-      {
-        "time": "13",
-        "val": 11.063026
-      },
-      {
-        "time": "13",
-        "val": 11.063026
-      },
-      {
-        "time": "13",
-        "val": 11.063026
-      },
-      {
-        "time": "13",
-        "val": 11.063026
-      },
-      {
-        "time": "13",
-        "val": 11.063026
-      },
-      {
-        "time": "17",
-        "val": 7.52
-      },
-      {
-        "time": "18",
-        "val": 7.8
-      },
-      {
-        "time": "19",
-        "val": 8.44
-      }
-    ]
-
-   
-    const echart = echarts.init(echartRef.value, 'light');
-    echart.setOption(areaOptions)
+const createLineChat = (data) => {
+  const [xAxisData, yData] = data.reduce((acc, { time, val }) => {
+    acc[0].push(time);
+    acc[1].push(val);
+    return acc;
+  }, [[], []]);
+
+  const seriesPast = replaceArray([...yData], yData.length - 3, 3, null);
+  const seriesFuture = replaceArray([...yData], 0, 5, null);
+  const option = getAreaOptions({xAxisData, seriesList: [seriesPast, seriesFuture]});
+  chart.setOption(option);
 }
 
 // 欢迎 - 问答
@@ -111,10 +80,7 @@ const handleWelcomeRecommend = question => {
 }
 
 onMounted(() => {
-  // const chart = new Chart({
-  //   container: 'chartContainer',
-  // });
-  initLineChat();
+  chart = echarts.init(echartRef.value, 'light');
 })
 </script>
 
@@ -170,9 +136,20 @@ onMounted(() => {
           </div>
         </div>
         <div class="echart-warpper">
+          <span>{{ chartTitle }}</span>
           <div id="chartContainer" class="w-[600px] h-[200px]" ref="echartRef"></div>
+          <ul class="flex justify-between w-[600px] text-center text-[12px] text-[#666] leading-[18px]">
+            <li class="w-[370px] pl-[40px]">
+              <span class="inline-block w-[10px] h-[2px] mb-[2px] mr-[4px] bg-[#2185da]"></span>
+              <span>过去</span>
+            </li>
+            <li class="flex-1 pr-[30px]">
+              <span class="inline-block w-[10px] h-[2px] mb-[2px] mr-[4px] bg-[#2ee055]"></span>
+              <span>未来</span>
+            </li>
+          </ul>
         </div>
-        
+
       </ChatBaseCard>
 
       <ChatAnswer :loading="false" :delay-loading="false" :toggleVisibleIcons="false" :content="answerResult"
@@ -187,9 +164,9 @@ onMounted(() => {
   display: flex;
   align-items: center;
   justify-content: center;
+  flex-flow: column;
   width: 100%;
-  height: 260px;
-  // padding: 10px;
+  padding: 50px 0 30px 0;
   border-radius: 8px;
   // background: #eee;
   // border: 1px solid #ccc;