Browse Source

fix图表 title字体大小修改

liujiejie 2 tháng trước cách đây
mục cha
commit
f8eae8b94d

+ 6 - 0
src/App.vue

@@ -24,6 +24,12 @@ body {
   width: 100%;
   height: 100%;
 }
+::-webkit-scrollbar {
+  display: none;
+}
+::-webkit-scrollbar {
+  display: none;
+}
 .fade-enter-active,
 .fade-leave-active {
   transition: opacity 0.5s ease;

+ 2 - 2
src/components/map/index.vue

@@ -275,9 +275,9 @@ export default {
     //   // -------------【结束】-------------
     //     const targetExtent = [106.8, 34.3, 118.6, 41.2];
     //     this.map.getView().fit(targetExtent, { duration: 2000 });
-    
+
     // }
-// 这个放在外面
+    // 这个放在外面
     this.initEvent();
   },
   methods: {

+ 6 - 6
src/views/overview/components/min_pitch/index.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2025-01-09 18:08:13
- * @LastEditTime: 2025-02-26 10:45:08
+ * @LastEditTime: 2025-03-14 13:44:47
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/overview/components/min_pitch/index.vue
@@ -37,16 +37,16 @@
       <VirtualList
         :list="diagramRelationsDatas"
         keyField="fieldEngineCode"
-        :itemSize="500"
+        :itemSize="550"
         v-slot="{ item, index }"
       >
-        <TwoDMarkersChart
+        <ColorbarInitTwoDmarkersChart
           :setUpImgData="setUpImgData"
           :key="item.fieldEngineCode"
           :index="`${new Date().getTime()}` + index"
           :ref="item.fieldEngineCode"
           :fileAddr="item.fileAddr"
-        ></TwoDMarkersChart>
+        ></ColorbarInitTwoDmarkersChart>
       </VirtualList>
       <el-dialog
         v-if="isShowDescription"
@@ -97,7 +97,7 @@
 <script>
 import DicCard from "@/views/overview/components/dicCard/index.vue";
 import FilterChart from "@/views/overview/components/filterChart/index.vue";
-import TwoDMarkersChart from "@/views/performance/components/chartsCom/TwoDMarkersChart.vue";
+import ColorbarInitTwoDmarkersChart from "@/views/performance/components/chartsCom/ColorbarInitTwoDmarkersChart.vue";
 import TinymceEditor from "@/components/Tinymce.vue";
 import {
   analysisDetail,
@@ -110,7 +110,7 @@ export default {
   components: {
     DicCard,
     FilterChart,
-    TwoDMarkersChart,
+    ColorbarInitTwoDmarkersChart,
     TinymceEditor,
   },
   props: {

+ 5 - 5
src/views/overview/components/yaw_error_density/index.vue

@@ -26,7 +26,7 @@
       <VirtualList
         :list="diagramRelationsDatas"
         keyField="fileAddr"
-        :itemSize="500"
+        :itemSize="550"
         v-slot="{ item, index }"
       >
         <lineAndChildLine
@@ -38,7 +38,7 @@
           :fileAddr="item.fileAddr"
         >
         </lineAndChildLine>
-        <TwoDMarkersChart
+        <ColorbarInitTwoDmarkersChart
           v-else
           :setUpImgData="setUpImgData"
           :key="item.fieldEngineCode + index"
@@ -46,7 +46,7 @@
           :index="index + item.fieldEngineCode"
           :fileAddr="item.fileAddr"
         >
-        </TwoDMarkersChart>
+        </ColorbarInitTwoDmarkersChart>
       </VirtualList>
       <el-dialog
         v-if="isShowDescription"
@@ -97,7 +97,7 @@
 <script>
 import DicCard from "@/views/overview/components/dicCard/index.vue";
 import FilterChart from "@/views/overview/components/filterChart/index.vue";
-import TwoDMarkersChart from "@/views/performance/components/chartsCom/TwoDMarkersChart.vue";
+import ColorbarInitTwoDmarkersChart from "@/views/performance/components/chartsCom/ColorbarInitTwoDmarkersChart.vue";
 import TinymceEditor from "@/components/Tinymce.vue";
 import lineAndChildLine from "@/views/performance/components/chartsCom/lineAndChildLine.vue";
 import {
@@ -111,7 +111,7 @@ export default {
     DicCard,
     FilterChart,
     TinymceEditor,
-    TwoDMarkersChart,
+    ColorbarInitTwoDmarkersChart,
     lineAndChildLine,
   },
   props: {

+ 17 - 16
src/views/overview/js/colors.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2025-02-17 15:31:57
- * @LastEditTime: 2025-02-18 15:22:20
+ * @LastEditTime: 2025-03-14 13:43:27
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/overview/js/colors.js
@@ -30,18 +30,19 @@ export const colorSchemes = [
   {
     label: "复古",
     colors: [
-      "#387FC9",
+      "#FFB7A6",
       "#715219",
       "#EA7637",
-      "#182B7C",
       "#B6B642",
+      "#FF7F50",
       "#C83629",
       "#672064",
       "#E48179",
+      "#D15D42",
       "#459BAF",
       "#FF69B4",
       "#800080",
-      "#7C3B6C",
+      "#9B3D2F",
       "#DAA520",
       "#BC8F8F",
       "#F5DEB3",
@@ -75,19 +76,19 @@ export const colorSchemes = [
   {
     label: "淡雅",
     colors: [
-      "#97A2F9",
+      "#F1E1C6",
       "#EA8783",
       "#F5C380",
       "#F7E87C",
-      "#9EE68F",
+      "#D1E4D0",
       "#62B6F6",
       "#7FAAF0",
       "#C49DF9",
-      "#424348",
+      "#B6A6C5",
       "#32CD32",
       "#8B008B",
       "#FFD700",
-      "#32CD32",
+      "#A49BB1",
       "#A9A9A9",
       "#B9E9E2",
       "#FF6347",
@@ -120,19 +121,19 @@ export const colorSchemes = [
   {
     label: "商务",
     colors: [
-      "#294F91",
+      "#A6B3C1",
       "#555555",
       "#B26F28",
       "#2B666A",
-      "#B83C38",
+      "#4A6D7C",
       "#615B9B",
       "#898989",
       "#9B982F",
-      "#377C57",
+      "#2F3A47",
       "#A52A2A",
       "#B8860B",
       "#6A5ACD",
-      "#20B2AA",
+      "#1D2329",
       "#D3D3D3",
       "#708090",
       "#2F4F4F",
@@ -166,19 +167,19 @@ export const colorSchemes = [
   {
     label: "简洁",
     colors: [
-      "#949FF8",
+      "#F0F6F7",
       "#ABDEFC",
       "#F3AC9B",
       "#A989F7",
-      "#8DC1F9",
+      "#A8D1D5",
       "#AF65AE",
       "#423E78",
       "#E48178",
-      "#449CB0",
+      "#5FA9B0",
       "#F5F5F5",
       "#FFD700",
       "#DC143C",
-      "#32CD32",
+      "#2B666A",
       "#FF6347",
       "#00FA9A",
       "#FF1493",

+ 11 - 2
src/views/performance/components/PlotlyCharts.vue

@@ -17,8 +17,17 @@
             :key="index"
             :label="scheme.label"
             :value="scheme.colors"
-            :style="getOptionStyle(scheme.colors)"
-          ></el-option>
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span>
+          </el-option>
         </el-select>
         <!-- <span style="margin-left: 10px">自定义颜色</span> -->
       </div>

+ 11 - 2
src/views/performance/components/chartsCom/3DDrawingChart.vue

@@ -15,8 +15,17 @@
             :key="index"
             :label="scheme.label"
             :value="scheme.colors"
-            :style="getOptionStyle(scheme.colors)"
-          ></el-option>
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span>
+          </el-option>
         </el-select>
       </div>
     </div>

+ 557 - 0
src/views/performance/components/chartsCom/ColorbarInitTwoDmarkersChart.vue

@@ -0,0 +1,557 @@
+<!--
+ * @Author: your name
+ * @Date: 2025-03-14 10:30:00
+ * @LastEditTime: 2025-03-14 13:44:25
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/views/performance/components/chartsCom/colorbarInitTwoDmarkersChart.vue
+-->
+<template>
+  <div style="width: 100%; height: 500px">
+    <!-- 2D散点图 -->
+    <div style="display: flex; align-items: center; padding-top: 20px">
+      <div style="margin-right: 20px; display: flex; align-items: center">
+        <el-select
+          size="small"
+          v-model="color1"
+          @change="updateChartColor"
+          placeholder="选择配色方案"
+          style="width: 200px"
+        >
+          <el-option
+            v-for="(scheme, index) in colorSchemes"
+            :key="index"
+            :label="scheme.label"
+            :value="scheme.colors"
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span
+          ></el-option>
+        </el-select>
+        <span style="margin-left: 10px">自定义颜色</span>
+      </div>
+      <!-- 图表类型切换按钮 -->
+      <div>
+        <el-button size="small" @click="setChartType('scatter')"
+          >散点图</el-button
+        >
+        <el-button size="small" @click="setChartType('line')">折线图</el-button>
+      </div>
+    </div>
+    <!-- 点大小控制 -->
+    <div style="display: flex; align-items: center">
+      <!-- <span style="margin-right: 10px">点大小</span> -->
+      <el-slider
+        v-model="pointSize"
+        :min="2"
+        :max="15"
+        :step="1"
+        label="点的大小"
+        show-stops
+        style="width: 150px"
+        @change="updateChartColor"
+      ></el-slider>
+    </div>
+    <div
+      v-loading="loading"
+      :ref="'plotlyChart-' + index"
+      style="width: 100%; height: 500px"
+    >
+      <el-empty v-if="isError" description="请求失败"></el-empty>
+    </div>
+  </div>
+</template>
+
+<script>
+import Plotly from "plotly.js-dist";
+import axios from "axios";
+import { myMixin } from "@/mixins/chartRequestMixin";
+import { colorSchemes } from "@/views/overview/js/colors";
+import { mapState } from "vuex";
+export default {
+  props: {
+    fileAddr: {
+      default: "",
+      type: String,
+    },
+    index: {
+      type: String,
+    },
+    setUpImgData: {
+      default: () => [],
+      type: Array,
+    },
+  },
+  data() {
+    return {
+      pointSize: 4, // 默认点大小
+      color1: colorSchemes[0].colors, // 默认颜色
+      // 配色方案列表(每个方案是一个颜色数组)
+      colorSchemes: [...colorSchemes],
+      chartData: {},
+      chartType: "scatter", // 初始化为散点图 (scatter)
+      // color1: "", // 默认颜色
+      selectedPoints: [],
+      originalColors: [],
+      originalSizes: [],
+    };
+  },
+  computed: {
+    ...mapState("themes", {
+      themeColor: "themeColor",
+    }),
+  },
+  watch: {
+    themeColor: {
+      handler() {
+        this.color1 = this.themeColor;
+        this.updateChartColor();
+      },
+      deep: true,
+    },
+    setUpImgData: {
+      handler(newType) {
+        this.drawChart();
+      },
+      deep: true,
+    },
+  },
+  mixins: [myMixin],
+  async mounted() {
+    this.getData();
+    this.color1 = this.themeColor;
+  },
+  methods: {
+    // 根据配色方案设置每个选项的样式
+    getOptionStyle(scheme) {
+      return {
+        background: `linear-gradient(to right, ${scheme
+          .slice(0, 8)
+          .join(", ")})`,
+        color: "#fff",
+        height: "30px",
+        lineHeight: "30px",
+        borderRadius: "0px",
+      };
+    },
+    async getData() {
+      if (this.fileAddr !== "") {
+        try {
+          this.loading = true;
+          this.cancelToken = axios.CancelToken.source();
+          const resultChartsData = await axios.get(this.fileAddr, {
+            cancelToken: this.cancelToken.token,
+          });
+          if (typeof resultChartsData.data === "string") {
+            let dataString = resultChartsData.data;
+            // 如果数据字符串的开头和结尾可能有多余的字符(比如非法字符),可以进行清理
+            dataString = dataString.trim(); // 去除前后空格
+            // 如果数据包含了类似 "Infinity" 或其他无法解析的字符,替换它们
+            dataString = dataString.replace(/Infinity/g, '"Infinity"'); // 例如,将 "Infinity" 转换为字符串
+            try {
+              const parsedData = JSON.parse(dataString);
+              this.chartData = parsedData;
+            } catch (error) {
+              console.error("JSON 解析失败:", error);
+            }
+          } else {
+            this.chartData = resultChartsData.data;
+          }
+          this.drawChart();
+          this.isError = false;
+          this.loading = false;
+        } catch (error) {
+          this.isError = true;
+          this.loading = false;
+        }
+      }
+    },
+    // 清理非法字符(如换行符等)
+    cleanJsonString(jsonString) {
+      return jsonString.replace(/[\n\r\t]/g, "").replace(/,\s*([\]}])/g, "$1"); // 清理换行符等
+    },
+    drawChart() {
+      if (!this.$refs[`plotlyChart-${this.index}`]) {
+        return false;
+      }
+      const data = this.chartData.data && this.chartData.data[0];
+      let trace = {};
+      // 保存原始颜色和大小
+      this.originalColors = [...data.yData];
+      this.originalSizes = new Array(data.xData.length).fill(6); // 初始点大小
+
+      if (this.chartType === "scatter") {
+        // 如果有 colorbar 数据
+        const uniqueTimeLabels =
+          data.colorbar && data.colorbar.length === data.xData.length
+            ? [...new Set(data.colorbar)] // 从 colorbar 中提取唯一的标签
+            : [...new Set(data.yData)]; // 如果没有 colorbar,使用 data.color
+        const ticktext = uniqueTimeLabels.map((dateStr) => dateStr); // 格式化为标签
+        const tickvals = uniqueTimeLabels.map((label, index) => index + 1); // 设置 tick 值
+        const timeMapping = uniqueTimeLabels.reduce((acc, curr, index) => {
+          acc[curr] = index + 1;
+          return acc;
+        }, {});
+        // 获取 colorbar 的最小值和最大值来计算比例值
+        const minValue = Math.min(...new Set(uniqueTimeLabels));
+        const maxValue = Math.max(...new Set(uniqueTimeLabels));
+        const colorStops = [
+          this.color1[0],
+          this.color1[4],
+          this.color1[8],
+          this.color1[12],
+        ];
+        // 计算渐变比例
+        const colors = colorStops.map((color, index) => {
+          const proportion = index / (colorStops.length - 1); // 计算比例值 (0, 1/3, 2/3, 1)
+          return [proportion, color]; // 创建比例-颜色映射
+        });
+        // 确保 colors 至少有 2 种颜色,否则使用默认颜色
+        if (colors.length < 2) {
+          colors.push([1, colorStops[colorStops.length - 1] || "#1B2973"]);
+        }
+
+        // 计算颜色值映射
+        let colorValues = [];
+        if (data.colorbar && data.colorbar.length === data.xData.length) {
+          colorValues = data.colorbar.map((date) => timeMapping[date]);
+        } else {
+          colorValues = data.yData.map((date) => timeMapping[date]);
+        }
+        // 绘制 2D 散点图
+        trace = {
+          x: data.xData,
+          y: data.yData,
+          mode: "markers",
+          type: "scattergl", // 使用 scattergl 提高性能
+          text: data.engineName, // 提示文本
+          marker: {
+            color: data.colorbar, // 根据 colorbar 映射的数字设置颜色
+            colorscale: this.color1
+              ? colors // 如果有 color1 使用自定义颜色比例
+              : [
+                  [0, "#F9FDD2"],
+                  [0.15, "#E9F6BD"],
+                  [0.3, "#C2E3B9"],
+                  [0.45, "#8AC8BE"],
+                  [0.6, "#5CA8BF"],
+                  [0.75, "#407DB3"],
+                  [0.9, "#2E4C9A"],
+                  [1, "#1B2973"],
+                ], // 默认颜色渐变
+            colorbar: data.colorbar
+              ? { title: data.colorbartitle || "Color Legend" }
+              : undefined, // 如果有 colorbar 显示,否则不显示
+            size: new Array(data.xData.length).fill(this.pointSize), // 点的大小
+            line: {
+              color: "#fff", // 让边框颜色和点颜色相同
+              width: 0.3, // 设置边框宽度
+            },
+          },
+        };
+        if (data.colorbartitle === "密度") {
+          trace.marker.cmin = 0;
+          trace.marker.cmax = maxValue;
+        } else if (data.colorbartitle === "百分比(%)") {
+          trace.marker.cmin = 0;
+          trace.marker.cmax = 100;
+        }
+        if (data.colorbar) {
+          trace.customdata = data.colorbar || data.color;
+          trace.hovertemplate =
+            `${this.chartData.xaixs}:` +
+            ` %{x} <br> ` +
+            `${this.chartData.yaixs}:` +
+            "%{y} <br> " +
+            `${data.colorbartitle}:` +
+            `%{customdata}<br><extra></extra>`;
+        } else {
+          trace.hovertemplate =
+            `${this.chartData.xaixs}:` +
+            ` %{x} <br> ` +
+            `${this.chartData.yaixs}:` +
+            "%{y} " +
+            `<extra></extra>`;
+        }
+      } else if (this.chartType === "line") {
+        // 折线图
+        trace = {
+          x: data.xData,
+          y: data.yData,
+          mode: "lines",
+          type: "scattergl", // 使用 scattergl 提高性能
+          text: data.engineName,
+          line: {
+            color: this.color1 || "#FF5733", // 使用自定义颜色
+          },
+        };
+      } else if (this.chartType === "bar") {
+        // 柱状图
+        trace = {
+          x: data.xData,
+          y: data.yData,
+          type: "bar", // 柱状图
+          marker: {
+            color: this.color1 || "#FF5733", // 使用自定义颜色
+          },
+        };
+      }
+
+      // 图表布局
+      let layout = {
+        title: {
+          text: data.title,
+          font: {
+            size: 16,
+            weight: "bold",
+          },
+        },
+        xaxis: {
+          title: this.chartData.xaixs,
+          gridcolor: "rgb(255,255,255)", // 网格线颜色
+          tickcolor: "rgb(255,255,255)",
+          linecolor: "#fff",
+          linewidth: 2, // 轴线宽度(确保颜色生效)
+          showbackground: true, // 显示背景
+          zeroline: false, // 显示 X 轴的中轴线
+        },
+        yaxis: {
+          title: this.chartData.yaixs,
+          linecolor: "#fff",
+          gridcolor: "rgb(255,255,255)", // 网格线颜色
+          tickcolor: "rgb(255,255,255)",
+          linewidth: 1, // 轴线宽度(确保颜色生效)
+          showbackground: true, // 显示背景
+          zeroline: false, // 显示 X 轴的中轴线
+        },
+        showlegend: false,
+        plot_bgcolor: "#e5ecf6",
+        gridcolor: "#fff", // 设置网格线颜色
+      };
+
+      const getChartSetUp = (axisTitle) => {
+        return this.setUpImgData.find((item) => item.text.includes(axisTitle));
+      };
+
+      const xChartSetUp = getChartSetUp(layout.xaxis.title);
+      if (xChartSetUp) {
+        layout.xaxis.dtick = xChartSetUp.dtick;
+        layout.xaxis.range = [xChartSetUp.min, xChartSetUp.max];
+      }
+
+      const yChartSetUp = getChartSetUp(layout.yaxis.title);
+      if (yChartSetUp) {
+        layout.yaxis.dtick = yChartSetUp.dtick;
+        layout.yaxis.range = [yChartSetUp.min, yChartSetUp.max];
+      }
+
+      if (this.chartData.xaixs === "时间") {
+        layout.xaxis.type = "date";
+        layout.xaxis.tickformat = "%Y-%m-%d";
+      }
+
+      const config = {
+        modeBarButtonsToAdd: [
+          {
+            name: "选择",
+            icon: Plotly.Icons.pencil,
+            click: (gd) => this.handleSelectClick(gd),
+          },
+          {
+            name: "清除选中",
+            icon: Plotly.Icons.undo,
+            click: (gd) => this.handleClearSelect(gd),
+          },
+          {
+            name: "下载CSV文件",
+            icon: Plotly.Icons.disk,
+            click: (gd) => this.handleDownloadCSV(gd),
+          },
+        ],
+        modeBarButtonsToRemove: [
+          // 移除不需要的工具按钮
+          "lasso2d",
+        ],
+        displaylogo: false,
+        editable: true,
+        scrollZoom: false,
+      };
+      this.$nextTick(() => {
+        // 使用 Plotly 绘制图表
+        Plotly.react(
+          this.$refs[`plotlyChart-${this.index}`],
+          [trace],
+          layout,
+          config
+        ).then(() => {
+          // 确保在图表加载完成后设置工具栏按钮
+          const plotElement = this.$refs[`plotlyChart-${this.index}`];
+          Plotly.relayout(plotElement, layout); // 使用 relayout 来确保自定义按钮应用
+        });
+      });
+    },
+
+    generateHSLColor(index, total) {
+      const hue = (index / total) * 360; // 色相值从 0 到 360
+      return `hsl(${hue}, 100%, 50%)`; // 饱和度和亮度设置为固定值,生成多样的颜色
+    },
+    handleSelectClick(gd) {
+      // 绑定 plotly_click 事件
+      gd.on("plotly_click", (data) => {
+        const pointIndex = data.points[0].pointIndex;
+        const xClick = data.points[0].x;
+        const yClick = data.points[0].y;
+
+        // 将点击的点添加到选中的点数组
+        this.selectedPoints.push({
+          x: xClick, // 点击点的 x 坐标
+          y: yClick, // 点击点的 y 坐标
+          index: pointIndex, // 点击点的索引
+          time: data.points[0].text, // 点击点的时间信息
+        });
+
+        // 初始化颜色和大小数组
+        let newColors = [...this.originalColors];
+        let newSize = [...this.originalSizes];
+
+        // 如果选中的点数大于等于3,进行多边形选择区域的处理
+        if (this.selectedPoints.length >= 3) {
+          const xv = this.selectedPoints.map((p) => p.x);
+          const yv = this.selectedPoints.map((p) => p.y);
+
+          // 判断点是否在多边形内
+          function inPolygon(x, y, xv, yv) {
+            let inside = false;
+            for (let i = 0, j = xv.length - 1; i < xv.length; j = i++) {
+              const intersect =
+                yv[i] > y !== yv[j] > y &&
+                x < ((xv[j] - xv[i]) * (y - yv[i])) / (yv[j] - yv[i]) + xv[i];
+              if (intersect) inside = !inside;
+            }
+            return inside;
+          }
+
+          // 用于跟踪已添加的 (x, y) 组合
+          const addedPoints = {};
+
+          // 遍历图表数据中的所有点,检查是否在多边形内
+          gd.data[0].x.forEach((xVal, i) => {
+            const yVal = gd.data[0].y[i];
+            if (inPolygon(xVal, yVal, xv, yv)) {
+              const pointKey = `${xVal}-${yVal}`;
+              if (!addedPoints[pointKey]) {
+                this.selectedPoints.push({
+                  x: gd.data[0].x[i],
+                  y: gd.data[0].y[i],
+                  time: gd.data[0].text[i],
+                });
+
+                newColors[i] = "red"; // 高亮选择的点
+                newSize[i] = 10; // 设置点的大小
+                addedPoints[pointKey] = true;
+              }
+            }
+          });
+        }
+
+        // 更新选中点的颜色和大小
+        this.selectedPoints.forEach((point) => {
+          newColors[point.index] = "red";
+          newSize[point.index] = 10;
+        });
+
+        // 使用 Plotly.restyle 更新颜色和大小
+        Plotly.restyle(gd, {
+          "marker.color": [newColors],
+          "marker.size": [newSize],
+        });
+
+        // 确保选中的点在最上面
+        const scatterTrace = gd.data[0]; // 原来的散点数据
+        const selectedTrace = {
+          x: this.selectedPoints.map((p) => p.x),
+          y: this.selectedPoints.map((p) => p.y),
+          mode: "markers",
+          type: "scattergl",
+          marker: {
+            color: "red", // 选中点颜色
+            size: 10,
+          },
+        };
+
+        // 合并数据,并保证选中点在最后
+        const updatedTraces = [scatterTrace, selectedTrace]; // 选中的点 `selectedTrace` 放在最后
+
+        // 更新图表
+        Plotly.react(gd, updatedTraces, gd.layout);
+
+        // 处理选中的数据
+        this.getSelectData(this.selectedPoints, gd.layout);
+      });
+    },
+    handleClearSelect(gd) {
+      this.selectedPoints = [];
+      Plotly.restyle(gd, {
+        "marker.color": [this.originalColors],
+        "marker.size": [this.originalSizes],
+      });
+    },
+    getSelectData(selectedPoints, layout) {
+      // 在这里处理选中的数据,您可以将其展示或导出等
+      console.log("选中的点数据:", selectedPoints);
+    },
+    handleDownloadCSV(gd) {
+      if (this.selectedPoints.length === 0) {
+        alert("没有选中的数据,请选择数据后进行文件下载。");
+        return;
+      }
+      this.downloadCSV();
+    },
+
+    downloadCSV() {
+      const headers = [this.chartData.xaixs, this.chartData.yaixs];
+      const csvRows = [headers]; // 保存标头
+      // 使用 Set 或 Map 去重
+      const uniquePoints = [];
+      this.selectedPoints.forEach((point) => {
+        if (!uniquePoints.some((p) => p.x === point.x && p.y === point.y)) {
+          uniquePoints.push(point);
+        }
+      });
+
+      // 将去重后的点加入 CSV 数据
+      uniquePoints.forEach((point) => {
+        csvRows.push(`${point.x},${point.y}`);
+      });
+
+      const csvString = csvRows.join("\n");
+      const blob = new Blob([csvString], { type: "text/csv; charset=utf-8" });
+      const url = URL.createObjectURL(blob);
+      const a = document.createElement("a");
+      a.href = url;
+      a.download = "selected_data.csv";
+      a.click();
+      URL.revokeObjectURL(url);
+    },
+    setChartType(type) {
+      // 切换图表类型
+      this.chartType = type;
+      this.drawChart(); // 重新绘制图表
+    },
+
+    updateChartColor(color) {
+      // 更新图表颜色
+      this.drawChart();
+    },
+  },
+};
+</script>
+
+<style scoped></style>

+ 12 - 3
src/views/performance/components/chartsCom/GeneratorTemperature.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2025-01-21 11:18:49
- * @LastEditTime: 2025-03-13 16:43:59
+ * @LastEditTime: 2025-03-13 17:10:32
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/chartsCom/GeneratorTemperature.vue
@@ -23,8 +23,17 @@
             :key="index"
             :label="scheme.label"
             :value="scheme.colors"
-            :style="getOptionStyle(scheme.colors)"
-          ></el-option>
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span>
+          </el-option>
         </el-select>
         <!-- <span style="margin-left: 10px">自定义颜色</span> -->
       </div>

+ 11 - 2
src/views/performance/components/chartsCom/Time3DChart.vue

@@ -15,8 +15,17 @@
             :key="index"
             :label="scheme.label"
             :value="scheme.colors"
-            :style="getOptionStyle(scheme.colors)"
-          ></el-option>
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span>
+          </el-option>
         </el-select>
       </div>
     </div>

+ 63 - 21
src/views/performance/components/chartsCom/TwoDMarkersChart.vue

@@ -15,7 +15,16 @@
             :key="index"
             :label="scheme.label"
             :value="scheme.colors"
-            :style="getOptionStyle(scheme.colors)"
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span
           ></el-option>
         </el-select>
         <span style="margin-left: 10px">自定义颜色</span>
@@ -58,6 +67,7 @@ import axios from "axios";
 import { myMixin } from "@/mixins/chartRequestMixin";
 import { colorSchemes } from "@/views/overview/js/colors";
 import { mapState } from "vuex";
+import { isArray, isString } from "@/utils/validate";
 export default {
   props: {
     fileAddr: {
@@ -176,7 +186,6 @@ export default {
           data.colorbar && data.colorbar.length === data.xData.length
             ? [...new Set(data.colorbar)] // 从 colorbar 中提取唯一的标签
             : [...new Set(data.yData)]; // 如果没有 colorbar,使用 data.color
-
         const ticktext = uniqueTimeLabels.map((dateStr) => dateStr); // 格式化为标签
         const tickvals = uniqueTimeLabels.map((label, index) => index + 1); // 设置 tick 值
         const timeMapping = uniqueTimeLabels.reduce((acc, curr, index) => {
@@ -184,21 +193,25 @@ export default {
           return acc;
         }, {});
         // 获取 colorbar 的最小值和最大值来计算比例值
-        const minValue = Math.min(...tickvals);
-        const maxValue = Math.max(...tickvals);
-
-        // 创建颜色比例映射
-        const colors = ticktext.map((item, ind) => {
-          const proportion = ind / (ticktext.length - 1); // 0 到 1 的比例值,取决于 ticktext 的位置
-          const colorIndex = Math.floor(proportion * (this.color1.length - 1)); // 计算颜色池索引
-          const defaultColor = this.color1[colorIndex]; // 获取对应的颜色
-          return [
-            proportion, // 比例值
-            defaultColor, // 对应颜色池中的颜色
-          ];
+        const minValue = Math.min(...new Set(uniqueTimeLabels));
+        const maxValue = Math.max(...new Set(uniqueTimeLabels));
+        const colorStops = [
+          this.color1[0],
+          this.color1[4],
+          this.color1[8],
+          this.color1[12],
+        ];
+        // 计算渐变比例
+        const colors = colorStops.map((color, index) => {
+          const proportion = index / (colorStops.length - 1); // 计算比例值 (0, 1/3, 2/3, 1)
+          return [proportion, color]; // 创建比例-颜色映射
         });
+        // 确保 colors 至少有 2 种颜色,否则使用默认颜色
+        if (colors.length < 2) {
+          colors.push([1, colorStops[colorStops.length - 1] || "#1B2973"]);
+        }
 
-        // 将时间字符串映射为数字
+        // 计算颜色值映射
         let colorValues = [];
         if (data.colorbar && data.colorbar.length === data.xData.length) {
           colorValues = data.colorbar.map((date) => timeMapping[date]);
@@ -226,17 +239,46 @@ export default {
                   [0.9, "#2E4C9A"],
                   [1, "#1B2973"],
                 ], // 默认颜色渐变
-            colorbar: data.colorbar
-              ? { title: data.colorbartitle || "Color Legend" }
-              : undefined, // 如果有 colorbar 显示,否则不显示
+            // colorbar: data.colorbar
+            //   ? { title: data.colorbartitle || "Color Legend" }
+            //   : undefined, // 如果有 colorbar 显示,否则不显示
             size: new Array(data.xData.length).fill(this.pointSize), // 点的大小
           },
-          hovertemplate:
+        };
+        if (data.colorbartitle === "密度") {
+          trace.marker.cmin = 0;
+          trace.marker.cmax = maxValue;
+        } else if (data.colorbartitle === "百分比(%)") {
+          trace.marker.cmin = 0;
+          trace.marker.cmax = 100;
+        }
+        if (data.colorbar && isArray(data.colorbar)) {
+          trace.hovertemplate =
             `${this.chartData.xaixs}:` +
             ` %{x} <br> ` +
             `${this.chartData.yaixs}:` +
-            "%{y} <br> <extra></extra>",
-        };
+            "%{y} <br> " +
+            `${data.colorbartitle}:` +
+            `%{customdata}<br><extra></extra>`;
+          trace.customdata = data.colorbar || data.color;
+        } else {
+          if (data.colorbar && isString(data.colorbar)) {
+            trace.hovertemplate =
+              `${this.chartData.xaixs}:` +
+              ` %{x} <br> ` +
+              `${this.chartData.yaixs}:` +
+              "%{y} <br> " +
+              `${data.colorbartitle}:` +
+              `${data.colorbar}<br><extra></extra>`;
+          } else {
+            trace.hovertemplate =
+              `${this.chartData.xaixs}:` +
+              ` %{x} <br> ` +
+              `${this.chartData.yaixs}:` +
+              "%{y} " +
+              `<extra></extra>`;
+          }
+        }
       } else if (this.chartType === "line") {
         // 折线图
         trace = {

+ 11 - 2
src/views/performance/components/chartsCom/lineAndChildLine.vue

@@ -14,8 +14,17 @@
           :key="index"
           :label="scheme.label"
           :value="scheme.colors"
-          :style="getOptionStyle(scheme.colors)"
-        ></el-option>
+        >
+          <span
+            v-for="color in scheme.colors.slice(0, 8)"
+            :style="{
+              background: color,
+              width: '20px',
+              height: '20px',
+              display: 'inline-block',
+            }"
+          ></span>
+        </el-option>
       </el-select>
       <div>
         <el-button size="small" @click="toggleChartType">

+ 49 - 16
src/views/performance/components/chartsCom/powerMarkers2DCharts.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-09-11 14:32:12
- * @LastEditTime: 2025-03-13 16:58:03
+ * @LastEditTime: 2025-03-13 17:55:17
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/chartsCom/powerMarkers2DCharts.vue
@@ -26,8 +26,17 @@
               :key="index"
               :label="scheme.label"
               :value="scheme.colors"
-              :style="getOptionStyle(scheme.colors)"
-            ></el-option>
+            >
+              <span
+                v-for="color in scheme.colors.slice(0, 8)"
+                :style="{
+                  background: color,
+                  width: '20px',
+                  height: '20px',
+                  display: 'inline-block',
+                }"
+              ></span>
+            </el-option>
           </el-select>
         </div>
       </div>
@@ -181,25 +190,49 @@ export default {
       // 获取 yData 的最小值和最大值来做比例值的计算
       const minValue = Math.min(...tickvals);
       const maxValue = Math.max(...tickvals);
-      // 计算比例值
-      const colors = ticktext.map((item, ind) => {
-        // 计算比例值(可以根据需要调整映射的数据范围)
-        const proportion = (tickvals[ind] - minValue) / (maxValue - minValue);
-        return [
-          proportion, // 比例值
-          this.color1[ind], // 对应的颜色
-        ];
+      // // 计算比例值
+      // const colors = ticktext.map((item, ind) => {
+      //   // 计算比例值(可以根据需要调整映射的数据范围)
+      //   const proportion = (tickvals[ind] - minValue) / (maxValue - minValue);
+      //   return [
+      //     proportion, // 比例值
+      //     this.color1[ind], // 对应的颜色
+      //   ];
+      // });
+      // // 将时间字符串映射为数字
+      // let colorValues = [];
+      // // data.colorbar.map((date, index) => timeMapping[date]);
+      // if (data.colorbar) {
+      //   colorValues = data.colorbar.map((date, index) => timeMapping[date]);
+      // } else {
+      //   colorValues = data.color.map((date, index) => timeMapping[date]);
+      // }
+      // 仅取 this.color1 的前 4 种颜色进行渐变
+      const colorStops = [
+        this.color1[0],
+        this.color1[4],
+        this.color1[8],
+        this.color1[12],
+      ];
+
+      // 计算渐变比例
+      const colors = colorStops.map((color, index) => {
+        const proportion = index / (colorStops.length - 1); // 计算比例值 (0, 1/3, 2/3, 1)
+        return [proportion, color]; // 生成颜色映射
       });
 
-      // 将时间字符串映射为数字
+      // 确保至少有 2 个颜色,否则使用默认颜色
+      if (colors.length < 2) {
+        colors.push([1, colorStops[colorStops.length - 1] || "#1B2973"]);
+      }
+
+      // 计算颜色值映射
       let colorValues = [];
-      // data.colorbar.map((date, index) => timeMapping[date]);
       if (data.colorbar) {
-        colorValues = data.colorbar.map((date, index) => timeMapping[date]);
+        colorValues = data.colorbar.map((date) => timeMapping[date]);
       } else {
-        colorValues = data.color.map((date, index) => timeMapping[date]);
+        colorValues = data.color.map((date) => timeMapping[date]);
       }
-
       let scatterTrace = {}; // 用于存放散点图的 trace
       let lineTrace = {}; // 用于存放折线图的 trace
 

+ 12 - 3
src/views/performance/components/chartsCom/yawErrorLine.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2025-01-22 09:42:59
- * @LastEditTime: 2025-03-13 16:56:32
+ * @LastEditTime: 2025-03-13 17:11:47
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/chartsCom/yawErrorLine.vue
@@ -23,8 +23,17 @@
             :key="index"
             :label="scheme.label"
             :value="scheme.colors"
-            :style="getOptionStyle(scheme.colors)"
-          ></el-option>
+          >
+            <span
+              v-for="color in scheme.colors.slice(0, 8)"
+              :style="{
+                background: color,
+                width: '20px',
+                height: '20px',
+                display: 'inline-block',
+              }"
+            ></span>
+          </el-option>
         </el-select>
         <!-- <span style="margin-left: 10px">自定义颜色</span> -->
       </div>