Преглед изворни кода

cp图表的封装\散点图处理+数据筛选过滤

liujiejie пре 6 месеци
родитељ
комит
d817233de1

+ 4 - 11
src/assets/js/constants/echarts-config/Cp.js

@@ -1,16 +1,14 @@
 /*
  * @Author: your name
  * @Date: 2024-11-19 16:22:48
- * @LastEditTime: 2024-11-20 17:21:07
- * @LastEditors: milo-MacBook-Pro.local
+ * @LastEditTime: 2024-11-21 15:44:18
+ * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/assets/js/constants/echarts-config/Cp.js
-//  */
-// 风能利用系数图
+ */
+// 风能利用系数图 散点折线图
 // 用途:分析风能利用系数(Cp)与风速或叶尖速比的关系。
 // 适用场景:风机效率优化。
-// 实现建议:
-// 使用 ECharts 的折线图或散点图。
 export const option = {
   title: {
     text: "风速与功率输出对比",
@@ -20,7 +18,6 @@ export const option = {
   xAxis: {
     type: "category",
     scale: true,
-    max: 30, // 风速最大值为30m/s,视具体数据调整
     axisLabel: {
       show: true,
       interval: "auto",
@@ -28,10 +25,6 @@ export const option = {
     },
     show: true,
     name: "风速(m/s)",
-    nameLocation: "center",
-    nameTextStyle: {
-      padding: [20, 0, 0, 0],
-    },
   },
   yAxis: {
     type: "value",

+ 8 - 7
src/assets/js/constants/echarts-config/Heatmap.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-20 09:13:21
- * @LastEditTime: 2024-11-20 09:47:51
+ * @LastEditTime: 2024-11-21 15:33:44
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/assets/js/constants/echarts-config/Heatmap.js
@@ -18,7 +18,6 @@ export const option = {
   toolbox: {
     feature: {
       dataView: { show: true, readOnly: false },
-      //   magicType: { show: true, type: ["line", "bar"] },
       restore: { show: true },
       saveAsImage: { show: true },
     },
@@ -34,12 +33,14 @@ export const option = {
     name: "风向",
   },
   visualMap: {
-    min: 0,
-    max: 20, // 风速范围
+    // min: 0,
+    // max: 20, // 风速范围
     calculable: true,
-    orient: "horizontal",
-    left: "center",
-    bottom: "15%",
+    realtime: false,
+    orient: "vertical",
+    right: 20,
+    top: "center",
+    // bottom: "15%",
   },
   series: [
     {

+ 2 - 3
src/assets/js/constants/echarts-config/pareto.js

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2024-11-20 09:19:45
- * @LastEditTime: 2024-11-20 17:21:33
- * @LastEditors: milo-MacBook-Pro.local
+ * @LastEditTime: 2024-11-21 14:55:59
+ * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/assets/js/constants/echarts-config/pareto.js
  */
@@ -43,7 +43,6 @@ export const option = {
     {
       type: "value",
       name: "累积百分比 (%)",
-      max: 100,
     },
   ],
   series: [

+ 12 - 5
src/assets/js/constants/echarts-config/radar.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-04 11:33:31
- * @LastEditTime: 2024-11-20 09:50:04
+ * @LastEditTime: 2024-11-21 10:03:46
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/assets/js/constants/echarts-config/radar.js
@@ -12,13 +12,18 @@ export const option = {
   tooltip: {},
   radar: {
     indicator: [
-      { name: "风速", max: 20 },
-      { name: "发电量", max: 5000 },
-      { name: "利用系数", max: 1 },
+      { name: "风速" }, //这个是X轴维度值,类型 对应value 下标
+      { name: "发电量" },
+      { name: "利用系数" },
+      // { name: "玉峰店" }, //这个是X轴维度值,类型 对应value 下标
+      // { name: "朝阳店" },
+      // { name: "大理店" },
     ],
   },
   legend: {
     top: "bottom",
+    data: ["风电场 A", "风电场 B"],
+    // data: ["单价", "客单价"],
   },
   toolbox: {
     feature: {
@@ -35,11 +40,13 @@ export const option = {
       data: [
         {
           value: [12, 4000, 0.8],
-          name: "风电场 A",
+          name: "风电场 A", //值 机组数据 y轴指标
+          // name: "单价",
         },
         {
           value: [15, 4500, 0.85],
           name: "风电场 B",
+          // name: "客单价",
         },
       ],
     },

+ 10 - 2
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/index.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-20 11:18:08
- * @LastEditTime: 2024-11-20 14:43:14
+ * @LastEditTime: 2024-11-21 15:41:37
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/utils/chartLogic/index.js
@@ -9,4 +9,12 @@
 
 import { handleBarChartLogic } from "./modules/barAndLine";
 import { handleScatterChartLogic } from "./modules/scatter";
-export { handleBarChartLogic, handleScatterChartLogic };
+import { handleRadarChartLogic } from "./modules/radar";
+import { handleCpChartLogic } from "./modules/cp";
+
+export {
+  handleBarChartLogic,
+  handleScatterChartLogic,
+  handleRadarChartLogic,
+  handleCpChartLogic,
+};

+ 97 - 0
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/cp.js

@@ -0,0 +1,97 @@
+/*
+ * @Author: your name
+ * @Date: 2024-11-21 15:40:30
+ * @LastEditTime: 2024-11-21 15:40:49
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/cp.js
+ */
+//散点折线图
+import { filterData } from "../dargChartFIlter";
+import { getFormattedLabels, getFormattedSeries } from "../../configFn";
+export function handleCpChartLogic(
+  item,
+  formLabelAlign,
+  formFilterAlign,
+  isFilter,
+  type
+) {
+  // 封装柱状图的具体逻辑
+  if (isFilter === "filter") {
+    // 数据筛选逻辑
+    const filterResult = formLabelAlign.Ydata.map((yItem, index) => ({
+      label: yItem.label,
+      id: yItem.id,
+      data: yItem.data.map((val) => {
+        const filters = formFilterAlign[index]?.filters || [];
+        return filters.length > 0 && !filters.includes(val[yItem.label])
+          ? null
+          : val;
+      }),
+    }));
+    // 条件筛选逻辑
+    const filterList = filterResult.map((filteredItem, index) => {
+      const filter = formFilterAlign[index];
+      const { filterType1, filterType2, number1, number2 } = filter;
+      if (!filterType1 && !filterType2 && number1 == null && number2 == null) {
+        return {
+          label: filteredItem.label,
+          id: filteredItem.id,
+          data: filteredItem.data,
+        };
+      } else {
+        const filterDatas = filterData(
+          filter,
+          filteredItem.data,
+          filteredItem.label
+        );
+        return {
+          label: filteredItem.label,
+          id: filteredItem.id,
+          data: [...filterDatas],
+        };
+      }
+    });
+    item.Xdata = formLabelAlign.Xdata;
+    item.Ydata = filterList;
+  } else {
+    item.Xdata = formLabelAlign.Xdata;
+    item.Ydata = formLabelAlign.Ydata;
+  }
+
+  item.option.xAxis = {
+    ...item.option.xAxis,
+    name: formLabelAlign.Xlable,
+  };
+  item.option.yAxis = {
+    ...item.option.yAxis,
+    name: formLabelAlign.Ylable,
+  };
+
+  if (item.Ydata[0]?.data?.length > 0) {
+    item.option.series = getFormattedSeries(item.Ydata, type);
+  }
+  if (item.Xdata[0]?.data?.length > 0) {
+    item.option.xAxis = {
+      ...item.option.xAxis,
+      data: item.Xdata[0].data,
+      axisTick: { alignWithLabel: true },
+      axisLabel: {
+        formatter: (value, index) =>
+          value !== null ? getFormattedLabels(index, item.Xdata, value) : "",
+      },
+    };
+    item.option.tooltip = {
+      trigger: "axis",
+      axisPointer: { type: "shadow" },
+      formatter: (params) => {
+        const index = params[0]?.dataIndex; // 获取当前数据点索引
+        const content = params
+          .map((param) => `${param.marker}${param.seriesName}: ${param.value}`)
+          .join("<br/>");
+        const customLabels = getFormattedLabels(index, item.Xdata);
+        return `${customLabels}<br/>${content}`;
+      },
+    };
+  }
+}

+ 128 - 0
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/radar.js

@@ -0,0 +1,128 @@
+/*
+ * @Author: your name
+ * @Date: 2024-11-21 09:40:55
+ * @LastEditTime: 2024-11-21 14:15:21
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/radar.js
+ */
+//雷达图
+
+import { filterData } from "../dargChartFIlter";
+
+export function handleRadarChartLogic(
+  item, // 当前编辑项配置
+  formLabelAlign, // 每一项 label 显示
+  formFilterAlign, // 过滤数据筛选
+  isFilter, // 是否是过滤
+  type // 图表类型
+) {
+  // 检查基础数据
+  if (!item || !formLabelAlign) {
+    console.error("handleRadarChartLogic: 缺少必要参数");
+    return;
+  }
+
+  // 数据筛选逻辑
+  if (isFilter === "filter") {
+    const filterResult = formLabelAlign.Ydata.map((yItem, index) => ({
+      label: yItem.label,
+      id: yItem.id,
+      data: yItem.data
+        .map((val) => {
+          const filters = formFilterAlign[index]?.filters || [];
+          // 如果值不在过滤条件内,返回 null
+          return filters.length > 0 && !filters.includes(val[yItem.label])
+            ? null
+            : val;
+        })
+        .filter((vals) => vals !== null), // 直接过滤掉 null 值
+    }));
+
+    const filterList = filterResult.map((filteredItem, index) => {
+      const filter = formFilterAlign[index];
+      const { filterType1, filterType2, number1, number2 } = filter;
+      if (!filterType1 && !filterType2 && number1 == null && number2 == null) {
+        return {
+          label: filteredItem.label,
+          id: filteredItem.id,
+          data: filteredItem.data,
+        };
+      } else {
+        const filterDatas = filterData(
+          filter,
+          filteredItem.data,
+          filteredItem.label
+        );
+        return {
+          label: filteredItem.label,
+          id: filteredItem.id,
+          data: [...filterDatas],
+        };
+      }
+    });
+
+    item.Xdata = formLabelAlign.Xdata;
+    item.Ydata = filterList.map((fitem, ind) => {
+      return {
+        ...fitem,
+        data: fitem.data.filter((fval) => fval !== null),
+      };
+    });
+    console.log(filterList, item.Ydata, "filterList");
+  } else {
+    item.Xdata = formLabelAlign.Xdata;
+    item.Ydata = formLabelAlign.Ydata;
+  }
+
+  // 设置纬度(indicator)并去重
+  if (item.Xdata.length > 0 && item.Xdata[0].data?.length > 0) {
+    const radarIndicators = Array.from(
+      new Set(
+        item.Xdata.flatMap((xItem) =>
+          xItem.data.map((xVal) => xVal[xItem.label])
+        )
+      )
+    )
+      .filter((name) => name !== undefined) // 过滤掉 undefined
+      .map((name) => ({ name }));
+
+    item.option.radar.indicator = radarIndicators;
+  }
+
+  // 设置系列(series),对相同纬度的数据值进行求和
+  if (
+    item.Ydata.length > 0 &&
+    item.Ydata[0]?.data?.length > 0 &&
+    item.Xdata.length > 0 &&
+    item.Xdata[0]?.data?.length > 0
+  ) {
+    const seriesData = item.Ydata.map((yItem) => {
+      const summedValues = item.option.radar.indicator.map((indicator) => {
+        const filteredValues = yItem.data.filter(
+          (yVal) => yVal[item.Xdata[0].label] === indicator.name
+        );
+
+        // 跳过 null 和非数字值
+        return filteredValues.reduce((sum, val) => {
+          const numericValue = Number(val[yItem.label]);
+          return !isNaN(numericValue) ? sum + numericValue : sum;
+        }, 0);
+      });
+
+      return {
+        name: yItem.label,
+        value: summedValues,
+      };
+    });
+
+    item.option.series = [
+      {
+        type: "radar",
+        data: seriesData,
+      },
+    ];
+  } else {
+    item.option.series = []; // 无数据时清空系列
+  }
+}

+ 3 - 3
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/scatter.js

@@ -1,4 +1,4 @@
-//散点图+散点折线图+雷达图
+//散点图+散点折线图
 import { filterData } from "../dargChartFIlter";
 export function handleScatterChartLogic(
   item, //curEdit编辑项配置
@@ -61,7 +61,7 @@ export function handleScatterChartLogic(
   };
 
   if (item.Ydata[0]?.data?.length > 0 || item.Xdata[0]?.data?.length > 0) {
-    console.log(item.Xdata, "item.Xdata", item.Ydata);
+    // console.log(item.Xdata, "item.Xdata", item.Ydata);
     item.option.series = (
       item.Xdata.length > item.Ydata.length ? item.Xdata : item.Ydata
     ).map((val, ind) => {
@@ -86,7 +86,7 @@ export function handleScatterChartLogic(
           ];
         })
         .filter((point) => point !== null); // 过滤掉无效的点
-      console.log(scatterData, "scatterData");
+      //   console.log(scatterData, "scatterData");
       return {
         name: `${item.Xdata[ind]?.label || "X"} - ${
           item.Ydata[ind]?.label || "Y"

+ 54 - 23
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/title.vue

@@ -88,6 +88,7 @@
             ></i>
           </el-tooltip>
         </div>
+        {{ formLabelAlign.Ydata[0].label }}
         <template v-for="(item, ind) in formLabelAlign.Ydata">
           <div class="attributeItemData">
             <el-select
@@ -166,14 +167,13 @@
               multiple
               collapse-tags
             >
-              <!-- <el-option label="全部" value="all"></el-option> -->
               <el-option
-                v-for="(item, index) in itemFilter.data"
+                v-for="(item, index) in itemFilter?.data"
                 :label="
-                  item[itemFilter.label] ? `${item[itemFilter.label]} ` : `0`
+                  item[itemFilter?.label] ? `${item[itemFilter?.label]} ` : `0`
                 "
-                :value="item[itemFilter.label]"
-                :key="item[itemFilter.label] + '' + index"
+                :value="item[itemFilter?.label]"
+                :key="item[itemFilter?.label] + '' + index"
               >
               </el-option>
             </el-select>
@@ -230,12 +230,13 @@
 </template>
 <script>
 import { mapState, mapMutations } from "vuex";
-// import { getFormattedLabels, getFormattedSeries } from "./configFn";
-// import { filterData } from "./chartLogic/dargChartFIlter";
 import {
   handleBarChartLogic,
   handleScatterChartLogic,
+  handleRadarChartLogic,
+  handleCpChartLogic,
 } from "./chartLogic/index";
+import Vue from "vue";
 export default {
   name: "title",
   props: {
@@ -327,7 +328,6 @@ export default {
     dataBaseCheckList: {
       handler(newVal) {
         this.disabled = !newVal.children?.length;
-
         this.selectData = newVal.children;
       },
       immediate: true, // 组件加载时立即检查
@@ -367,27 +367,30 @@ export default {
       );
     },
     updateAxisData(axisData) {
-      return axisData.map((item) => {
+      console.log(axisData, "axisData");
+      axisData.forEach((item, index) => {
         const selected = this.selectData.find(
           (val) => (val && val.id) === (item && item.id)
         );
         if (selected) {
-          return {
+          Vue.set(axisData, index, {
             ...item,
             label: selected.label || "",
             data: selected.fileData || [],
-          };
+          });
         }
-        return item;
       });
+      return axisData;
     },
+
     changeData() {
       if (this.$refs.form) {
         this.$refs.form.resetFields();
       }
-      //图表内容回显图表配置赋值
+      // 图表内容回显图表配置赋值
       if (this.curEdit && this.curEdit.option) {
-        this.formLabelAlign = {
+        // 使用 this.$set 替代直接赋值
+        this.$set(this, "formLabelAlign", {
           text: this.curEdit.option.title?.text || "",
           Xlable: this.curEdit.option.xAxis?.name || "",
           Ylable: this.curEdit.option.yAxis?.name || "",
@@ -411,15 +414,19 @@ export default {
                     id: "",
                   },
                 ],
-        };
-        //查找是否存在数据
+        });
+        // 查找是否存在数据
         const index = this.formFilterAlignData.findIndex(
           (item) => item.id === this.curEdit.id
         );
         if (index !== -1) {
-          this.formFilterAlign = this.formFilterAlignData[index]?.data;
+          this.$set(
+            this,
+            "formFilterAlign",
+            this.formFilterAlignData[index]?.data
+          );
         } else {
-          this.formFilterAlign = [
+          this.$set(this, "formFilterAlign", [
             {
               filters: [],
               filterType1: "",
@@ -428,7 +435,7 @@ export default {
               number2: null,
               radio: null,
             },
-          ];
+          ]);
         }
       } else {
         this.$message.warning("请选择一个图表进行编辑");
@@ -437,8 +444,11 @@ export default {
     //全部数据渲染
     changeChart(isFilter) {
       if (!this.curEdit?.option) return; // 确保 curEdit 和 option 存在
+      console.log(this.curEdit, this.formLabelAlign.Ydata, "this.curEdit");
       const item = JSON.parse(JSON.stringify(this.curEdit));
-      if (this.curEdit.type === "scatter") {
+
+      if (this.curEdit.type === "scatter" || this.curEdit.type === "radar") {
+        //判断散点选择的是否为number 或可转为number
         const isAllNumbers = (data) =>
           data.every((val) =>
             val.data.every((vals) => {
@@ -448,13 +458,19 @@ export default {
               );
             })
           );
-        // console.log(isAllNumbers(this.formLabelAlign.Xdata), "isAllNumbers");
         const isAllNumbersXdata = isAllNumbers(this.formLabelAlign.Xdata);
         const isAllNumbersYdata = isAllNumbers(this.formLabelAlign.Ydata);
-        if (!isAllNumbersXdata || !isAllNumbersYdata) {
+        if (
+          this.curEdit.type === "scatter" &&
+          (!isAllNumbersXdata || !isAllNumbersYdata)
+        ) {
           this.$message.warning("请选择数值项进行散点图绘制");
           return;
         }
+        if (this.curEdit.type === "radar" && !isAllNumbersYdata) {
+          this.$message.warning("指标值请选择数值项进行散点图绘制");
+          return;
+        }
       }
       // 确保标题和坐标轴对象存在
       item.option.title = item.option.title || {};
@@ -475,8 +491,23 @@ export default {
           isFilter,
           this.curEdit.type
         );
+      } else if (this.curEdit.type === "radar") {
+        handleRadarChartLogic(
+          item,
+          this.formLabelAlign,
+          this.formFilterAlign,
+          isFilter,
+          this.curEdit.type
+        );
+      } else if (this.curEdit.type === "Cp") {
+        handleCpChartLogic(
+          item,
+          this.formLabelAlign,
+          this.formFilterAlign,
+          isFilter,
+          this.curEdit.type
+        );
       }
-
       //设置仓库
       this.setFormFilterAlignData({
         id: this.curEdit.id,