Browse Source

开展同比增速页面开发,招商页面备份

littleblue55 1 month ago
parent
commit
9826344a26
4 changed files with 1881 additions and 620 deletions
  1. 11 0
      src/api/home.js
  2. 604 3
      src/views/growthRate/index.vue
  3. 618 617
      src/views/investment/index.vue
  4. 648 0
      src/views/investment/index_backup.vue

+ 11 - 0
src/api/home.js

@@ -21,4 +21,15 @@ export function getIndexData(query) {
         method: 'get',
         params: query
     })
+}
+
+// 获取首页数据
+export function getYearData(query) {
+    return request({
+        url: '/industry_oveview/industry_oveview/list/year',
+        method: 'get',
+        params: {
+            year: 0 
+        }
+    })
 }

+ 604 - 3
src/views/growthRate/index.vue

@@ -1,5 +1,606 @@
 <template>
-    <div class="">
-        同比增速
+  <!-- 同比增速 -->
+  <div :class="className" :style="{ height: '100%', width: width }">
+    <div class="select-container">
+      <el-form
+        style="
+          display: grid;
+          grid-template-columns: 1fr 1fr 1fr;
+          align-items: center;
+          grid-gap: 5px;
+        "
+        label-width="100px"
+      >
+        <el-form-item label="评估指标">
+          <el-select v-model="rateForm.selectedDataKey" style="width: 100%">
+            <el-option
+              v-for="key in dataKeys"
+              :key="key"
+              :value="key"
+              :label="keyToChinese[key]"
+            >
+              {{ keyToChinese[key] }}
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="行业">
+          <el-select v-model="rateForm.selectedIndustry" style="width: 100%" filterable>
+            <el-option
+                v-for="item in industryData"
+                :key="item.key"
+                :label="item.value"
+                :value="item.key"
+              >
+              </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="排序方式"> </el-form-item>
+        <el-form-item label="年度">
+          <el-select v-model="rateForm.selectedYear" style="width: 100%" filterable>
+            <el-option
+                v-for="key in yearsOptions"
+                :key="key"
+                :label="key"
+                :value="key"
+              >
+              </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="季度">
+          <el-select v-model="rateForm.selectedSeason" style="width: 100%" filterable>
+            <el-option
+                v-for="key in seasonOptions"
+                :key="key"
+                :label="key"
+                :value="key"
+              >
+              </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="企业分类"></el-form-item>
+        <el-form-item label="起始月度">
+          <el-select v-model="rateForm.selectedStartMonth" style="width: 100%" filterable>
+            <el-option
+                v-for="key in monthOptions"
+                :key="key"
+                :label="key"
+                :value="key"
+              >
+              </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="结束月度">
+          <el-select v-model="rateForm.selectedEndMonth" style="width: 100%" filterable>
+            <el-option
+                v-for="key in monthOptions"
+                :key="key"
+                :label="key"
+                :value="key"
+              >
+              </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item style="margin-bottom: 0">
+          <el-button
+            type="primary"
+            icon="el-icon-search"
+            @click="updateChart"
+            size="mini"
+            >搜索</el-button
+          >
+        </el-form-item>
+      </el-form>
     </div>
-</template>
+    <div ref="chart" :style="{ height: height, width: width }"></div>
+    <!-- littlegreen - 新增数据展示table -->
+    <el-table :data="tableData" border style="width: 100%">
+      <el-table-column
+        prop="industryName"
+        label="行业名称"
+        width="200"
+      ></el-table-column>
+      <el-table-column prop="year" label="年度" width="200"> </el-table-column>
+      <el-table-column prop="enterpriseId" label="企业ID"></el-table-column>
+      <el-table-column
+        prop="value"
+        :label="label"
+        width="200"
+      ></el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+import { getYearData } from "@/api/home";
+import { listBase_data_year } from "@/api/base_data_year/base_data_year";
+import { listIndustry, listAllIndustry } from "@/api/industry/industry"; // 导入行业数据的接口
+require("echarts/theme/macarons"); // echarts theme
+import resize from "@/views/dashboard/mixins/resize";
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: "chart",
+    },
+    width: {
+      type: String,
+      default: "100%",
+    },
+    height: {
+      type: String,
+      default: "400px",
+    },
+  },
+  data() {
+    return {
+      rateForm: {
+        selectedDataKey: "funding",
+        selectedIndustry: null,
+        selectedRange: null,
+        selectedYear: null,
+        selectedSeason: null,
+        selectedStartMonth: null,
+        selectedEndMonth: null,
+        selectEnterType: null,
+      },
+      seasonMap: new Map(),
+      monthMap: new Map(),
+      yearsOptions: [],
+      label: "评估指标值/万元",
+      chart: null,
+      chartData: [],
+      industryData: [],
+      industryMap: new Map(),
+      // 默认选择的字段
+      selectedCode: null,
+      dataKeys: [
+        "funding",
+        "energyConsume",
+        "paidTax",
+        "taxableIncome",
+        "totalIndustrialValue",
+        "powerConsume",
+      ], // 可选项
+      keyToChinese: {
+        landArea: "用地面积",
+        totalIndustrialValue: "工业总产值",
+        gdp: "工业增加值",
+        taxableIncome: "应税收入",
+        paidTax: "实缴税金",
+        mainBusinessIncome: "主营业务收入",
+        employeeNumber: "从业人员数",
+        profit: "利润总额",
+        ownerEquity: "所有者权益",
+        funding: "研发经费",
+        energyConsume: "能源消费量",
+        powerConsume: "电力消费量",
+      },
+      keyToUnit: {
+        landArea: "/亩",
+        totalIndustrialValue: "/万元",
+        gdp: "/万元",
+        taxableIncome: "/万元",
+        paidTax: "/万元",
+        mainBusinessIncome: "/万元",
+        employeeNumber: "/人",
+        profit: "/万元",
+        ownerEquity: "",
+        funding: "/万元",
+        energyConsume: "/万m³",
+        powerConsume: "/万KW·h",
+      },
+      selectedYear: null,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 2000000, // 默认 2000000 条(全部一次性数据)
+        enterpriseName: null,
+        location: null,
+        code: null,
+        mainBusiness: null,
+        landArea: null,
+        totalIndustrialValue: null,
+        gdp: null,
+        taxableIncome: null,
+        paidTax: null,
+        mainBusinessIncome: null,
+        employeeNumber: null,
+        profit: null,
+        ownerEquity: null,
+        funding: null,
+        energyConsume: null,
+        year: null,
+        month: null,
+      },
+      industryQueryParams: {
+        pageNum: 1,
+        pageSize: 2000000,
+        industryName: null,
+        code: null,
+      }, //  查询行业信息
+      availableYears: [],
+      selectedRange: 300, // 不能为 0
+      tableData: [],
+    };
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.fetchData();
+    });
+  },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose();
+    }
+  },
+  methods: {
+    fetchData() {
+      // 获取年份,获取季度、月度
+      getYearData()
+        .then((res) => {
+          this.yearsOptions = res.rows[0].years;
+          this.seasonMap = this.generateSeason(this.yearsOptions);
+          this.monthMap = this.generateMonthlyData(this.yearsOptions);
+          // console.log("monthMap", this.monthMap);
+        })
+        .catch((error) => {
+          console.error("Error fetching data:", error);
+        });
+      listAllIndustry()
+        .then((response) => {
+          // this.industryData = response.rows;
+          if (response && response?.rows) {
+              this.industryData = response.rows.map((item) => {
+                return {
+                  key: item.code,
+                  value: item.code + item.industryName,
+                };
+              });
+            }
+          // console.log("industryMap", this.industryMap);
+        })
+        .catch((error) => {
+          console.error("Error fetching data:", error);
+        });
+      // listBase_data_year(this.queryParams)
+      //   .then((response) => {
+      //     this.chartData = response.rows;
+      //     this.availableYears = [
+      //       ...new Set(this.chartData.map((item) => item.year)),
+      //     ];
+      //     this.selectedYear = this.availableYears[0] || null;
+      //     this.selectedCode = [
+      //       ...new Set(this.chartData.map((item) => item.code)),
+      //     ][0];
+      //     //   this.initChart();
+      //   })
+      //   .catch((error) => {
+      //     console.error("Error fetching data:", error);
+      //   });
+
+      // listIndustry(this.industryQueryParams)
+      //   .then((response) => {
+      //     this.industryData = response.rows;
+      //     // console.log("industry_info" + this.industryData);
+      //     this.industryMap = this.industryData.reduce((map, item) => {
+      //       const key = `${item.code}`; // 键是行业代码
+      //       map.set(key, item.industryName); // 将键和对应的行业名称存储到Map中
+      //       return map;
+      //     }, new Map());
+      //   })
+      //   .catch((error) => {
+      //     console.error("Error fetching data:", error);
+      //   });
+    },
+    initChart() {
+      if (this.chart) {
+        this.chart.dispose();
+      }
+      this.chart = echarts.init(this.$refs.chart, "macarons");
+      this.updateChart();
+    },
+    updateChart() {
+      console.log("updateChart", this.rateForm);
+    },
+    updateChartt() {
+      if (!this.chart) {
+        return;
+      }
+      let filteredData = this.chartData;
+      if (this.selectedYear) {
+        filteredData = filteredData.filter(
+          (item) =>
+            item.year === this.selectedYear && item.code === this.selectedCode
+        );
+      }
+      const values = filteredData.map((item) => item[this.selectedDataKey]);
+      const minVal = 0;
+      const maxVal = Math.max(...values);
+      // console.log(filteredData, values, this.selectedDataKey, 898);
+      if (
+        this.selectedRange === null ||
+        this.selectedRange === "" ||
+        isNaN(+this.selectedRange)
+      )
+        this.selectedRange = "100";
+      else if (Number(this.selectedRange) <= 0) this.selectedRange = "100";
+
+      const binCount = Math.ceil(
+        (maxVal - minVal) / Number(this.selectedRange)
+      );
+
+      let maxNum = -1;
+
+      // 生成区间标签和频次
+      const histogramData = [];
+      for (let i = 0; i < binCount; i++) {
+        const x0 = minVal + i * Number(this.selectedRange);
+        const x1 = Math.min(x0 + Number(this.selectedRange), maxVal);
+        const label = `${x0}-${x1}`;
+        let count = 0;
+        count += values.filter((value) => value >= x0 && value < x1).length;
+        if (x1 === maxVal) {
+          count += values.filter((value) => value === maxVal).length;
+        }
+
+        if (count > 0) {
+          if (count > maxNum) {
+            maxNum = count;
+          }
+          histogramData.push({ name: label, value: count });
+        }
+      }
+
+      const maxHistogramValue = Math.max(
+        ...histogramData.map((item) => item.value)
+      );
+      const totalHistogramValue = histogramData.reduce(
+        (sum, item) => sum + item.value,
+        0
+      );
+
+      // const quadraticData = this.generateQuadraticData(binCount, maxHistogramValue, totalHistogramValue);
+      // littlegreen - 去掉line和scatter
+      const option = {
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow",
+          },
+          formatter: (params) => {
+            // 使用箭头函数来保持 this 的上下文
+            const seriesName = params[0].name; // 系列名称
+            const dataIndex = params[0].dataIndex; // 数据索引
+            const value = params[0].data; // 实际的数据值
+            const xAxisLabel = params[0].axisValueLabel; // x轴的标签
+            const yAxisLabel = params[0].seriesName;
+            // 构建自定义的 tooltip 内容,包含年份
+            return `${xAxisLabel}<br> ${yAxisLabel}: ${value}`;
+          },
+        },
+        legend: {
+          data: [
+            `${this.selectedYear}年 ${
+              this.keyToChinese[this.selectedDataKey]
+            }企业数统计`,
+          ],
+        },
+        grid: {
+          left: "3%",
+          right: "4%",
+          bottom: "3%",
+          containLabel: true,
+        },
+        xAxis: {
+          type: "category",
+          name: "分布区间",
+          data: histogramData.map((item) => item.name),
+          axisLabel: {
+            fontSize: 12,
+            interval: 0,
+            rotate: 30,
+          },
+        },
+        yAxis: {
+          name: "企业数",
+          type: "value",
+          minInterval: 1,
+        },
+        series: [
+          {
+            name: `${this.selectedYear}年 ${
+              this.keyToChinese[this.selectedDataKey]
+            }企业数统计`,
+            type: "bar",
+            barWidth: "30%",
+            itemStyle: {
+              color: "rgba(245,0,0,0.6)",
+            },
+            data: histogramData.map((item) => item.value),
+            label: {
+              show: false, // 将show属性设置为false,去掉柱子上的数字
+            },
+          },
+          // {
+          //   type: "scatter",
+          //   symbol: "circle",
+          //   symbolSize: 10,
+          //   data: histogramData.map((item, index) => [index, item.value]),
+          //   itemStyle: {
+          //     color: "red",
+          //   },
+          // },
+          // {
+          //   type: "line",
+          //   data: histogramData.map((item, index) => [index, item.value]),
+          //   lineStyle: {
+          //     color: "#1a7cc8",
+          //   },
+          //   symbol: "none",
+          // },
+        ],
+      };
+      this.chart.setOption(option);
+      const that = this;
+      // littlegreen - chart增加点击事件,点击显示对应区间的企业列表
+      this.chart.on("click", function (param) {
+        //param参数包含的内容有:
+        //param.name:X轴的值
+        //param.data:Y轴的值
+        //param.value:Y轴的值
+        //param.type:点击事件均为click
+        //param.seriesName:legend的名称
+        //param.seriesIndex:系列序号(series中当前图形是第几个图形第几个)
+        //param.dataIndex:数值序列(X轴上当前点是第几个点)
+        //alert(param.seriesName);  //legend的名称
+        // console.log(param.name); //X轴的值 0-600 1.用-分割获得确定最小值和最大值 2.筛选filteredData中this.selectedDataKey的值符合要求的
+        const result = param.name.split("-").map(Number);
+        const filteredArray = filteredData.filter((item) => {
+          const isMaxValEqual = result[1] === maxVal;
+          const lowerBoundCheck = item[that.selectedDataKey] >= result[0];
+          const upperBoundCheck = isMaxValEqual
+            ? item[that.selectedDataKey] <= result[1]
+            : item[that.selectedDataKey] < result[1];
+
+          return lowerBoundCheck && upperBoundCheck;
+        });
+        that.tableData = filteredArray.map((item) => {
+          return {
+            industryName: item.code,
+            enterpriseId: item.enterpriseName,
+            year: item.year,
+            value: item[that.selectedDataKey],
+          };
+        });
+        // console.log(filteredData, result, that.selectedDataKey, filteredArray); //获取自定义的值
+      });
+    },
+    generateQuadraticData(binCount, maxHistogramValue, totalHistogramValue) {
+      const a = -0.01;
+      const h = binCount / 2;
+      const k = maxHistogramValue * 0.75;
+      const sideValue = (maxHistogramValue * 0.15) / 2;
+
+      const data = [];
+      for (let i = 0; i < binCount; i++) {
+        const x = i;
+        const y = a * (x - h) ** 2 + k;
+
+        // 调整两侧的值
+        if (i === 0 || i === binCount - 1) {
+          data.push([x, sideValue]);
+        } else {
+          data.push([x, y]);
+        }
+      }
+      return data;
+    },
+    generateSeason(years) {
+      const currentYear = new Date().getFullYear();
+      const currentMonth = new Date().getMonth() + 1;
+      const season = new Map();
+
+      years.forEach((year) => {
+        if (year === currentYear) {
+          // 当前年份,判断当前月份
+          if (currentMonth < 1) {
+            season.set(year, []);
+          } else if (currentMonth < 4) {
+            season.set(year, [1]); // 第一季度
+          } else if (currentMonth < 7) {
+            season.set(year, [1, 2]); // 前两季度
+          } else if (currentMonth < 10) {
+            season.set(year, [1, 2, 3]); // 前三季度
+          } else {
+            season.set(year, [1, 2, 3, 4]); // 四个季度
+          }
+        } else if (year < currentYear) {
+          // 过去的年份都包含四个季度
+          season.set(year, [1, 2, 3, 4]);
+        } else {
+          // 未来的年份
+          season.set(year, []);
+        }
+      });
+
+      return season;
+    },
+    generateMonthlyData(years) {
+      const currentYear = new Date().getFullYear();
+      const currentMonth = new Date().getMonth() + 1;
+      const monthlyData = new Map();
+      years.forEach((year) => {
+        if (year === currentYear) {
+          // 当前年份,判断当前月份
+          const months = Array.from({ length: currentMonth }, (_, i) => i + 1);
+          monthlyData.set(year, months); // 设置当前年份的已过月份
+        } else if (year < currentYear) {
+          // 过去的年份包含所有12个月
+          monthlyData.set(year, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
+        } else {
+          // 未来的年份
+          monthlyData.set(year, []);
+        }
+      });
+
+      return monthlyData;
+    },
+  },
+  watch: {
+    // littlegreen - 关闭监测数值变化
+    selectedDataKey() {
+      this.label = "评估指标值" + this.keyToUnit[this.selectedDataKey];
+    },
+    // selectedYear() {
+    //   this.updateChart();
+    // },
+    // selectedRange() {
+    //   setTimeout(this.updateChart, 2500);
+    // },
+    // selectedCode() {
+    //   this.updateChart();
+    // },
+  },
+  computed: {
+    seasonOptions() {
+        const options = this.rateForm.selectedYear ? this.seasonMap.get(this.rateForm.selectedYear) : [];
+        return options || []; // 以防得到 undefined
+    },
+    monthOptions() {
+        const options = this.rateForm.selectedYear ? this.monthMap.get(this.rateForm.selectedYear) : [];
+        return options || []; // 以防得到 undefined
+    }
+}
+
+};
+</script>
+
+<style scoped>
+.select-container {
+  margin: 10px 0;
+  font-size: 16px; /* 调整字号大小 */
+}
+
+.select-container select {
+  padding: 10px 20px; /* 增加内边距 */
+  margin-right: 10px; /* 增加右边距 */
+  border: 1px solid #121315; /* 蓝色边框 */
+  border-radius: 4px; /* 圆角边框 */
+  background-color: white; /* 背景色 */
+  color: #121315; /* 文字颜色 */
+  font-size: 16px; /* 调整字号大小 */
+  cursor: pointer; /* 鼠标悬停时的指针样式 */
+  outline: none; /* 移除焦点时的轮廓 */
+}
+
+.select-container select:hover {
+  border-color: #1a7cc8; /* 鼠标悬停时的边框颜色 */
+}
+
+.select-container select:focus {
+  border-color: #121315; /* 焦点时的边框颜色 */
+  box-shadow: 0 0 0 2px rgba(64, 159, 255, 0.2); /* 焦点时的阴影效果 */
+}
+</style>

+ 618 - 617
src/views/investment/index.vue

@@ -1,648 +1,649 @@
 <template>
-  <!-- 招商 - littlegreen - 补充form和label -->
-  <div
-    :class="className"
-    :style="{ height: '100%', width: width, padding: '20px' }"
-  >
-    <div class="select-container">
-      <el-form
-        :model="form"
-        :rules="rules"
-        ref="ruleForm"
-        style="
-          display: grid;
-          grid-template-columns: 1fr 1fr;
-          align-items: center;
-          grid-gap: 20px;
-        "
-      >
-        <el-form-item
-          label="新增企业月均工业产值"
-          label-width="200px"
-          prop="newMonthValue"
+    <!-- 招商 - littlegreen - 补充form和label -->
+    <div
+      :class="className"
+      :style="{ height: '100%', width: width, padding: '20px' }"
+    >
+      <div class="select-container">
+        <el-form
+          :model="form"
+          :rules="rules"
+          ref="ruleForm"
+          style="
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            align-items: center;
+            grid-gap: 5px;
+          "
         >
-          <div style="display: flex; align-items: cente">
-            <el-input
-              v-model.number="form.newMonthValue"
-              placeholder="请输入企业月均工业产值"
-              clearable
-            />
-            <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
-          </div>
-        </el-form-item>
-        <el-form-item label="行业代码" label-width="100px" prop="selectedCode">
-          <el-select v-model="form.selectedCode" style="width: 100%" filterable>
-            <el-option
-              v-for="item in selectedIndustryArray"
-              :key="item.key"
-              :label="item.value"
-              :value="item.key"
-            >
-            </el-option> </el-select
-        ></el-form-item>
-        <el-form-item
-          label="新增企业年实缴税金"
-          label-width="200px"
-          prop="newYearTax"
-        >
-          <!-- <el-input
-            v-model="form.newYearTax"
-            placeholder="请输入企业年实缴税金"
-            clearable
-          /> -->
-          <div style="display: flex; align-items: center">
-            <el-input
-              v-model.number="form.newYearTax"
+          <el-form-item
+            label="新增企业年工业产值"
+            label-width="200px"
+            prop="newMonthValue"
+          >
+            <div style="display: flex; align-items: cente">
+              <el-input
+                v-model.number="form.newMonthValue"
+                placeholder="请输入企业年工业产值"
+                clearable
+              />
+              <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
+            </div>
+          </el-form-item>
+          <el-form-item label="行业代码" label-width="100px" prop="selectedCode">
+            <el-select v-model="form.selectedCode" style="width: 100%" filterable>
+              <el-option
+                v-for="item in selectedIndustryArray"
+                :key="item.key"
+                :label="item.value"
+                :value="item.key"
+              >
+              </el-option> </el-select
+          ></el-form-item>
+          <el-form-item
+            label="新增企业年实缴税金"
+            label-width="200px"
+            prop="newYearTax"
+          >
+            <!-- <el-input
+              v-model="form.newYearTax"
               placeholder="请输入企业年实缴税金"
               clearable
-            />
-            <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
-          </div>
-        </el-form-item>
-        <el-form-item label="年度" style="margin-bottom: 0" label-width="100px" prop="selectedYear">
-          <el-select v-model="form.selectedYear" style="width: 100%">
-            <el-option
-              v-for="item in selectedYearArray"
-              :key="item.key"
-              :label="item.value"
-              :value="item.key"
+            /> -->
+            <div style="display: flex; align-items: center">
+              <el-input
+                v-model.number="form.newYearTax"
+                placeholder="请输入企业年实缴税金"
+                clearable
+              />
+              <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
+            </div>
+          </el-form-item>
+          <el-form-item label="年度" label-width="100px" prop="selectedYear">
+            <el-select v-model="form.selectedYear" style="width: 100%">
+              <el-option
+                v-for="item in selectedYearArray"
+                :key="item.key"
+                :label="item.value"
+                :value="item.key"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label-width="100px" style="margin-top: 20px;">
+            <el-button type="primary" size="mini" @click="submit">计算</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetForm"
+              >重置</el-button
             >
-            </el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label-width="100px">
-          <el-button type="primary" size="mini" @click="submit">计算</el-button>
-          <el-button icon="el-icon-refresh" size="mini" @click="resetForm"
-            >重置</el-button
-          >
-        </el-form-item>
-      </el-form>
-    </div>
-    <div>
-      <h4 v-show="calShow == 'low'" style="padding: 10px; text-align: center">
-        重新计算后输出:企业新增后比新增前行业得分平均降低{{ rate }}%
-      </h4>
-      <h4 v-show="calShow == 'high'" style="padding: 10px; text-align: center">
-        重新计算后输出:企业新增后比新增前行业得分平均提高{{ rate }}%
-      </h4>
-      <h4 v-show="calShow == 'same'" style="padding: 10px; text-align: center">
-        重新计算后输出:企业新增后与新增前行业得分平均一致
-      </h4>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div>
+        <h4 v-show="calShow == 'low'" style="padding: 10px; text-align: center">
+          重新计算后输出:企业新增后比新增前行业得分平均降低{{ rate }}%
+        </h4>
+        <h4 v-show="calShow == 'high'" style="padding: 10px; text-align: center">
+          重新计算后输出:企业新增后比新增前行业得分平均提高{{ rate }}%
+        </h4>
+        <h4 v-show="calShow == 'same'" style="padding: 10px; text-align: center">
+          重新计算后输出:企业新增后与新增前行业得分平均一致
+        </h4>
+      </div>
+      <div ref="chart" :style="{ height: height, width: width }"></div>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="year" label="年度" width="200"> </el-table-column>
+        <el-table-column prop="enterpriseId" label="企业ID"></el-table-column>
+        <el-table-column
+          prop="totalIndustrialValue"
+          label="企业月均工业产值"
+          width="200"
+        ></el-table-column>
+        <el-table-column
+          prop="value"
+          label="Z-score得分"
+          width="200"
+        ></el-table-column>
+      </el-table>
     </div>
-    <div ref="chart" :style="{ height: height, width: width }"></div>
-    <el-table :data="tableData" border style="width: 100%">
-      <el-table-column prop="year" label="年度" width="200"> </el-table-column>
-      <el-table-column prop="enterpriseId" label="企业ID"></el-table-column>
-      <el-table-column
-        prop="totalIndustrialValue"
-        label="企业月均工业产值"
-        width="200"
-      ></el-table-column>
-      <el-table-column
-        prop="value"
-        label="Z-score得分"
-        width="200"
-      ></el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script>
-import * as echarts from "echarts";
-import { listAllIndustry } from "@/api/industry/industry"; // 导入行业数据的接口
-import { listAllIndustry_run } from "@/api/industry_run/industry_run"; // 导入行业数据的接口
-require("echarts/theme/macarons"); // echarts theme
-import resize from "@/views/dashboard/mixins/resize";
-import { Decimal } from "decimal.js";
-import { getIndexData } from "@/api/home";
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: "chart",
-    },
-    width: {
-      type: String,
-      default: "100%",
-    },
-    height: {
-      type: String,
-      default: "400px",
-    },
-  },
-  data() {
-    return {
-      selectedYearArray: [],
-      calShow: "init",
-      rate: null,
-      chart: null,
-      chartData: [],
-      industryData: [],
-      industryMap: new Map(),
-      selectedDataKey: "totalIndustrialValueScore", // 默认选择的字段
-      form: {
-        selectedCode: null,
-        newMonthValue: null,
-        newYearTax: null,
-        selectedYear: null
+  </template>
+  
+  <script>
+  import * as echarts from "echarts";
+  import { listAllIndustry } from "@/api/industry/industry"; // 导入行业数据的接口
+  import { listAllIndustry_run } from "@/api/industry_run/industry_run"; // 导入行业数据的接口
+  require("echarts/theme/macarons"); // echarts theme
+  import resize from "@/views/dashboard/mixins/resize";
+  import { Decimal } from "decimal.js";
+  import { getIndexData } from "@/api/home";
+  
+  export default {
+    mixins: [resize],
+    props: {
+      className: {
+        type: String,
+        default: "chart",
       },
-      rules: {
-        selectedCode: [
-          { required: true, message: "请选择行业", trigger: "blur" },
-        ],
-        newMonthValue: [
-          {
-            required: true,
-            message: "请输入企业月均工业产值",
-            trigger: "blur",
-          },
-          { type: "number", message: "企业月均工业产值必须为数字" },
-        ],
-        newYearTax: [
-          {
-            type: "number",
-            message: "企业年实缴税金必须为数字",
-            trigger: "blur",
-          },
-        ],
-        selectedYear: [
-          { required: true, message: "请选择年度", trigger: "blur" },
-        ]
+      width: {
+        type: String,
+        default: "100%",
+      },
+      height: {
+        type: String,
+        default: "400px",
       },
-      selectedIndustryArray: [],
-      selectedYear: null,
-      selectedRange: 0.1, // 不能为 0, - littlegreen - 固定0.1
-      // littlegreen - 检测区间 和 表格数据
-      detectMin: null,
-      detectMax: null,
-      tableData: [],
-      scoreData: [],
-    };
-  },
-  mounted() {
-    this.$nextTick(() => {
-      this.fetchData();
-    });
-  },
-  beforeDestroy() {
-    if (this.chart) {
-      this.chart.dispose();
-    }
-  },
-  methods: {
-    // 拉取初始数据
-    async fetchData() {
-      const that = this;
-      // 获得所有行业
-      // that.selectedYear = new Date().getUTCFullYear() + "";
-      await listAllIndustry()
-        .then((res) => {
-          if (res && res?.rows) {
-            that.selectedIndustryArray = res.rows.map((item) => {
-              return {
-                key: item.code,
-                value: item.code + item.industryName,
-              };
-            });
-          }
-        })
-        .catch((error) => {
-          console.error("Error fetching data:", error);
-        });
-
-      await getIndexData({
-        year: 0,
-      })
-        .then((res) => {
-          if (res && res?.rows) {
-            that.selectedYearArray = res.rows[0].years.map((v) => {
-              return {
-                key: v,
-                value: v,
-              };
-            });
-          }
-        })
-        .catch((error) => {
-          console.error("Error fetching data:", error);
-        });
     },
-    // 提交表单
-    submit() {
-      this.$refs.ruleForm.validate((valid) => {
-        if (valid) {
-          this.handleData();
-        } else {
-          console.error("error submit!!");
-          return false;
-        }
-      });
+    data() {
+      return {
+        selectedYearArray: [],
+        calShow: "init",
+        rate: null,
+        chart: null,
+        chartData: [],
+        industryData: [],
+        industryMap: new Map(),
+        selectedDataKey: "totalIndustrialValueScore", // 默认选择的字段
+        form: {
+          selectedCode: null,
+          newMonthValue: null,
+          newYearTax: null,
+          selectedYear: null
+        },
+        rules: {
+          selectedCode: [
+            { required: true, message: "请选择行业", trigger: "blur" },
+          ],
+          newMonthValue: [
+            {
+              required: true,
+              message: "请输入企业月均工业产值",
+              trigger: "blur",
+            },
+            { type: "number", message: "企业月均工业产值必须为数字" },
+          ],
+          newYearTax: [
+            {
+              type: "number",
+              message: "企业年实缴税金必须为数字",
+              trigger: "blur",
+            },
+          ],
+          selectedYear: [
+            { required: true, message: "请选择年度", trigger: "blur" },
+          ]
+        },
+        selectedIndustryArray: [],
+        selectedYear: null,
+        selectedRange: 0.1, // 不能为 0, - littlegreen - 固定0.1
+        // littlegreen - 检测区间 和 表格数据
+        detectMin: null,
+        detectMax: null,
+        tableData: [],
+        scoreData: [],
+      };
     },
-    // 处理数据
-    handleData() {
-      // 1.拿当前年份和code的企业运行数据过来
-      // 2.计算每个企业的z-score
-      // 3.画图
-      const that = this;
-      listAllIndustry_run({
-        code: that.form.selectedCode,
-        year: that.form.selectedYear,
-      })
-        .then((res) => {
-          if (res && res.rows) {
-            that.scoreData = res.rows;
-            that.initChart();
-          }
-        })
-        .catch((error) => {
-          console.error("Error fetching data:", error);
-        });
+    mounted() {
+      this.$nextTick(() => {
+        this.fetchData();
+      });
     },
-    initChart() {
+    beforeDestroy() {
       if (this.chart) {
         this.chart.dispose();
       }
-      this.chart = echarts.init(this.$refs.chart, "macarons");
-      this.updateChart();
     },
-    updateChart() {
-      const that = this;
-      if (!this.chart) {
-        return;
-      }
-      let newMonthValue = new Decimal(that.form.newMonthValue).toNumber();
-      let total = [newMonthValue]; //总值
-      const result = Object.values(
-        that.scoreData.reduce((acc, item) => {
-          const key = item.enterpriseName; // 根据企业名称分组
-          let totalIndustrialValue = new Decimal(item.totalIndustrialValue);
-          if (!acc[key]) {
-            acc[key] = {
-              name: key,
-              data: [],
-              totalValue: new Decimal(0),
-              count: 0,
-            }; // 创建对象并初始化
+    methods: {
+      // 拉取初始数据
+      async fetchData() {
+        const that = this;
+        // 获得所有行业
+        // that.selectedYear = new Date().getUTCFullYear() + "";
+        await listAllIndustry()
+          .then((res) => {
+            if (res && res?.rows) {
+              that.selectedIndustryArray = res.rows.map((item) => {
+                return {
+                  key: item.code,
+                  value: item.code + item.industryName,
+                };
+              });
+            }
+          })
+          .catch((error) => {
+            console.error("Error fetching data:", error);
+          });
+  
+        await getIndexData({
+          year: 0,
+        })
+          .then((res) => {
+            if (res && res?.rows) {
+              that.selectedYearArray = res.rows[0].years.map((v) => {
+                return {
+                  key: v,
+                  value: v,
+                };
+              });
+            }
+          })
+          .catch((error) => {
+            console.error("Error fetching data:", error);
+          });
+      },
+      // 提交表单
+      submit() {
+        this.$refs.ruleForm.validate((valid) => {
+          if (valid) {
+            this.handleData();
+          } else {
+            console.error("error submit!!");
+            return false;
           }
-
-          acc[key].data.push(item); // 添加到对应的类别中
-          acc[key].totalValue = acc[key].totalValue.plus(totalIndustrialValue); // 累加 totalIndustrialValue
-          acc[key].count++; // 企业数 +1
-          return acc;
-        }, {})
-      ).map(({ name, data, totalValue, count }) => {
-        const totalIndustrialValue = totalValue.dividedBy(count).toNumber(); // 计算均值
-        total.push(totalIndustrialValue);
-        return { name, data, totalIndustrialValue }; // 返回结果
-      });
-      result.push({
-        name: "新企业",
-        data: [],
-        totalIndustrialValue: newMonthValue,
-      });
-
-      // littlegreen --计算增加新企业之后工业产值变化 计算全体企业 totalIndustrialValue 均值
-      const totalValues = result.map(
-        (e) => new Decimal(e.totalIndustrialValue)
-      );
-      const overallMean = totalValues
-        .reduce((sum, value) => sum.plus(value), new Decimal(0))
-        .dividedBy(totalValues.length);
-
-      // 计算不包括“新企业”的均值
-      const filteredValues = result
-        .filter((e) => e.name !== "新企业")
-        .map((e) => new Decimal(e.totalIndustrialValue));
-
-      const filteredMean = filteredValues
-        .reduce((sum, value) => sum.plus(value), new Decimal(0))
-        .dividedBy(filteredValues.length);
-      const relativeChange = overallMean.minus(filteredMean).dividedBy(filteredMean).mul(new Decimal(100));
-      // 显示增加/降低/一致
-      that.calShow = relativeChange.greaterThan(0) ? "high" : (relativeChange.lessThan(0)? "low" : "same")
-      // 增加的比率
-      that.rate = relativeChange.abs().toNumber().toFixed(2)
-
-      // 获取基础数据:最大值,最小值,平均值,标准差
-      function getBebeQ(numbers, digit = 2) {
-        let sum = numbers.reduce(
-          (acc, num) => acc.add(new Decimal(num)),
-          new Decimal(0)
-        );
-
-        let max = Math.max.apply(null, numbers);
-        let min = Math.min.apply(null, numbers);
-
-        // 平均值
-        let mean = sum.dividedBy(numbers.length);
-
-        // 计算每个数与均值的差的平方
-        const squaredDiffs = numbers.map((num) => {
-          const diff = new Decimal(num).minus(mean);
-          return diff.pow(2);
         });
-
-        // 计算平方差的均值
-        const sumOfSquaredDiffs = squaredDiffs.reduce(
-          (acc, diff) => acc.add(diff),
-          new Decimal(0)
+      },
+      // 处理数据
+      handleData() {
+        // 1.拿当前年份和code的企业运行数据过来
+        // 2.计算每个企业的z-score
+        // 3.画图
+        const that = this;
+        listAllIndustry_run({
+          code: that.form.selectedCode,
+          year: that.form.selectedYear,
+        })
+          .then((res) => {
+            if (res && res.rows) {
+              that.scoreData = res.rows;
+              that.initChart();
+            }
+          })
+          .catch((error) => {
+            console.error("Error fetching data:", error);
+          });
+      },
+      initChart() {
+        if (this.chart) {
+          this.chart.dispose();
+        }
+        this.chart = echarts.init(this.$refs.chart, "macarons");
+        this.updateChart();
+      },
+      updateChart() {
+        const that = this;
+        if (!this.chart) {
+          return;
+        }
+        let newMonthValue = new Decimal(that.form.newMonthValue).toNumber();
+        let total = [newMonthValue]; //总值
+        const result = Object.values(
+          that.scoreData.reduce((acc, item) => {
+            const key = item.enterpriseName; // 根据企业名称分组
+            let totalIndustrialValue = new Decimal(item.totalIndustrialValue);
+            if (!acc[key]) {
+              acc[key] = {
+                name: key,
+                data: [],
+                totalValue: new Decimal(0),
+                count: 0,
+              }; // 创建对象并初始化
+            }
+  
+            acc[key].data.push(item); // 添加到对应的类别中
+            acc[key].totalValue = acc[key].totalValue.plus(totalIndustrialValue); // 累加 totalIndustrialValue
+            acc[key].count++; // 企业数 +1
+            return acc;
+          }, {})
+        ).map(({ name, data, totalValue, count }) => {
+          const totalIndustrialValue = totalValue.dividedBy(count).toNumber(); // 计算均值
+          total.push(totalIndustrialValue);
+          return { name, data, totalIndustrialValue }; // 返回结果
+        });
+        result.push({
+          name: "新企业",
+          data: [],
+          totalIndustrialValue: newMonthValue,
+        });
+  
+        // littlegreen --计算增加新企业之后工业产值变化 计算全体企业 totalIndustrialValue 均值
+        const totalValues = result.map(
+          (e) => new Decimal(e.totalIndustrialValue)
         );
-
-        const variance = sumOfSquaredDiffs.dividedBy(numbers.length);
-
-        // 开平方得到标准差
-        const standardDeviation = variance.sqrt();
-
-        // 向上取整到最近的 0.1
-        const ceilingRoundedMax = Math.ceil(max * 10) / 10;
-
-        // 向下取整到最近的 0.1
-        const floorRoundedMin = Math.floor(min * 10) / 10;
-
-        return {
-          max: ceilingRoundedMax,
-          min: floorRoundedMin,
-          avg: parseFloat(mean.toNumber().toFixed(digit)) || 0,
-          stdDev: parseFloat(standardDeviation.toNumber().toFixed(digit)),
-        };
-      }
-
-      // 示例数据
-      const betaData = getBebeQ(total);
-      let newZScore;
-      const values = result.map((item) => {
-        let num = item.totalIndustrialValue;
-        const zScore = new Decimal(num)
-          .minus(betaData.avg)
-          .dividedBy(betaData.stdDev);
-        let scoreNum = zScore.toNumber();
-        if (new Decimal(num).equals(new Decimal(that.form.newMonthValue))) {
-          newZScore = scoreNum;
+        const overallMean = totalValues
+          .reduce((sum, value) => sum.plus(value), new Decimal(0))
+          .dividedBy(totalValues.length);
+  
+        // 计算不包括“新企业”的均值
+        const filteredValues = result
+          .filter((e) => e.name !== "新企业")
+          .map((e) => new Decimal(e.totalIndustrialValue));
+  
+        const filteredMean = filteredValues
+          .reduce((sum, value) => sum.plus(value), new Decimal(0))
+          .dividedBy(filteredValues.length);
+        const relativeChange = overallMean.minus(filteredMean).dividedBy(filteredMean).mul(new Decimal(100));
+        // 显示增加/降低/一致
+        that.calShow = relativeChange.greaterThan(0) ? "high" : (relativeChange.lessThan(0)? "low" : "same")
+        // 增加的比率
+        that.rate = relativeChange.abs().toNumber().toFixed(2)
+  
+        // 获取基础数据:最大值,最小值,平均值,标准差
+        function getBebeQ(numbers, digit = 2) {
+          let sum = numbers.reduce(
+            (acc, num) => acc.add(new Decimal(num)),
+            new Decimal(0)
+          );
+  
+          let max = Math.max.apply(null, numbers);
+          let min = Math.min.apply(null, numbers);
+  
+          // 平均值
+          let mean = sum.dividedBy(numbers.length);
+  
+          // 计算每个数与均值的差的平方
+          const squaredDiffs = numbers.map((num) => {
+            const diff = new Decimal(num).minus(mean);
+            return diff.pow(2);
+          });
+  
+          // 计算平方差的均值
+          const sumOfSquaredDiffs = squaredDiffs.reduce(
+            (acc, diff) => acc.add(diff),
+            new Decimal(0)
+          );
+  
+          const variance = sumOfSquaredDiffs.dividedBy(numbers.length);
+  
+          // 开平方得到标准差
+          const standardDeviation = variance.sqrt();
+  
+          // 向上取整到最近的 0.1
+          const ceilingRoundedMax = Math.ceil(max * 10) / 10;
+  
+          // 向下取整到最近的 0.1
+          const floorRoundedMin = Math.floor(min * 10) / 10;
+  
+          return {
+            max: ceilingRoundedMax,
+            min: floorRoundedMin,
+            avg: parseFloat(mean.toNumber().toFixed(digit)) || 0,
+            stdDev: parseFloat(standardDeviation.toNumber().toFixed(digit)),
+          };
         }
-        item.score = scoreNum;
-        return scoreNum;
-      });
-      // 计算 z-score 的基础数据
-      const scoreBasic = getBebeQ(values);
-      const center = new Decimal(scoreBasic.avg); // 确保 center 是 Decimal 类型
-      const interval = new Decimal(0.1);
-
-      // 使用 Decimal 来处理 minLimit 和 maxLimit
-      let minLimit = new Decimal(scoreBasic.min); // 向下取整到最近的0.1
-      let maxLimit = new Decimal(scoreBasic.max); // 向上取整到最近的0.1
-
-      // 确保 minLimit 和 maxLimit 关于 center 对称
-      if (!center.minus(minLimit).equals(maxLimit.minus(center))) {
-        const distanceToCenter = center
-          .minus(minLimit)
-          .gt(maxLimit.minus(center))
-          ? center.minus(minLimit)
-          : maxLimit.minus(center);
-
-        maxLimit = center.plus(distanceToCenter); // 更新 maxLimit 保持对称
-        minLimit = center.minus(distanceToCenter); // 更新 minLimit 保持对称
-      }
-
-      const intervals = [];
-      // 乘以1000 是将小数变成整数去计算,小数计算会有误差
-      for (
-        let i = minLimit * 1000;
-        i <= maxLimit * 1000;
-        i += interval * 1000
-      ) {
-        intervals.push(parseFloat((i / 1000).toFixed(2)));
-      }
-      // // 计算每个间隔的频次
-      const frequency = new Array(intervals.length - 1).fill(0); // 初始化频次数组
-
-      let intervalArr = intervals.slice(0, -1);
-      const intervalStrings = [];
-      for (let i = 0; i < intervalArr.length; i++) {
-        const start = intervalArr[i].toFixed(1); // 保留一位小数
-        const end = ((intervalArr[i] * 1000 + interval * 1000) / 1000).toFixed(
-          1
-        ); // 保留一位小数
-        intervalStrings.push({
-          name: `${start}-${end}`,
-          max: end,
-          min: start,
-        }); // 构建区间字符串
-      }
-
-      values.forEach((value) => {
-        for (let j = 0; j < intervalStrings.length; j++) {
-          // 保证包含右边界
-          let v = parseFloat(value) * 1000;
-          if (
-            v >= parseFloat(intervalStrings[j].min) * 1000 &&
-            v < parseFloat(intervalStrings[j].max) * 1000
-          ) {
-            frequency[j]++;
-            break; // 找到对应区间后可以跳出循环
+  
+        // 示例数据
+        const betaData = getBebeQ(total);
+        let newZScore;
+        const values = result.map((item) => {
+          let num = item.totalIndustrialValue;
+          const zScore = new Decimal(num)
+            .minus(betaData.avg)
+            .dividedBy(betaData.stdDev);
+          let scoreNum = zScore.toNumber();
+          if (new Decimal(num).equals(new Decimal(that.form.newMonthValue))) {
+            newZScore = scoreNum;
           }
+          item.score = scoreNum;
+          return scoreNum;
+        });
+        // 计算 z-score 的基础数据
+        const scoreBasic = getBebeQ(values);
+        const center = new Decimal(scoreBasic.avg); // 确保 center 是 Decimal 类型
+        const interval = new Decimal(0.1);
+  
+        // 使用 Decimal 来处理 minLimit 和 maxLimit
+        let minLimit = new Decimal(scoreBasic.min); // 向下取整到最近的0.1
+        let maxLimit = new Decimal(scoreBasic.max); // 向上取整到最近的0.1
+  
+        // 确保 minLimit 和 maxLimit 关于 center 对称
+        if (!center.minus(minLimit).equals(maxLimit.minus(center))) {
+          const distanceToCenter = center
+            .minus(minLimit)
+            .gt(maxLimit.minus(center))
+            ? center.minus(minLimit)
+            : maxLimit.minus(center);
+  
+          maxLimit = center.plus(distanceToCenter); // 更新 maxLimit 保持对称
+          minLimit = center.minus(distanceToCenter); // 更新 minLimit 保持对称
         }
-      });
-
-      // // 确保处理最大值等于maxLimit的情况
-      if (
-        values.some(
-          (value) => parseFloat(value) * 1000 == parseFloat(maxLimit) * 1000
-        )
-      ) {
-        frequency[frequency.length - 1]++;
-      }
-      // 1.计算正态分布值
-      const normalDistributionValues = intervals
-        .slice(0, -1)
-        .map((intervalStart, index) => {
-          const intervalEnd = intervals[index + 1];
-          const midpoint = (intervalStart + intervalEnd) / 2;
-
-          // 使用 Decimal 进行更高精度的计算
-          const midPointDecimal = new Decimal(midpoint);
-          const avgDecimal = new Decimal(scoreBasic.avg);
-          const stdDevDecimal = new Decimal(scoreBasic.stdDev);
-
-          const exponent = midPointDecimal
-            .minus(avgDecimal)
-            .dividedBy(stdDevDecimal)
-            .pow(2)
-            .negated()
-            .dividedBy(new Decimal(2));
-          const exponentValue = new Decimal(Math.exp(exponent.toNumber())); // 取自然指数
-          const coefficient = new Decimal(1).dividedBy(
-            stdDevDecimal.times(new Decimal(Math.sqrt(2 * Math.PI)))
-          );
-
-          return coefficient.times(exponentValue).toNumber(); // 返回计算结果
+  
+        const intervals = [];
+        // 乘以1000 是将小数变成整数去计算,小数计算会有误差
+        for (
+          let i = minLimit * 1000;
+          i <= maxLimit * 1000;
+          i += interval * 1000
+        ) {
+          intervals.push(parseFloat((i / 1000).toFixed(2)));
+        }
+        // // 计算每个间隔的频次
+        const frequency = new Array(intervals.length - 1).fill(0); // 初始化频次数组
+  
+        let intervalArr = intervals.slice(0, -1);
+        const intervalStrings = [];
+        for (let i = 0; i < intervalArr.length; i++) {
+          const start = intervalArr[i].toFixed(1); // 保留一位小数
+          const end = ((intervalArr[i] * 1000 + interval * 1000) / 1000).toFixed(
+            1
+          ); // 保留一位小数
+          intervalStrings.push({
+            name: `${start}-${end}`,
+            max: end,
+            min: start,
+          }); // 构建区间字符串
+        }
+  
+        values.forEach((value) => {
+          for (let j = 0; j < intervalStrings.length; j++) {
+            // 保证包含右边界
+            let v = parseFloat(value) * 1000;
+            if (
+              v >= parseFloat(intervalStrings[j].min) * 1000 &&
+              v < parseFloat(intervalStrings[j].max) * 1000
+            ) {
+              frequency[j]++;
+              break; // 找到对应区间后可以跳出循环
+            }
+          }
         });
-      const option = {
-        color: ["rgba(245,0,0,0.6)"],
-        dataZoom: [
-          {
-            type: "inside", // 内置于坐标系中
-            start: 0,
-            end: 100,
-            xAxisIndex: [0],
-          },
-        ],
-        tooltip: {
-          trigger: "axis",
-          axisPointer: {
-            type: "shadow",
-          },
-          formatter: (params) => {
-            // 使用箭头函数来保持 this 的上下文
-            const seriesName = params[0].name; // 系列名称
-            const dataIndex = params[0].dataIndex; // 数据索引
-            const value = params[0].data; // 实际的数据值
-            const xAxisLabel = params[0].axisValueLabel; // x轴的标签
-            const yAxisLabel = params[0].seriesName;
-            // 构建自定义的 tooltip 内容,包含年份
-            return `${xAxisLabel}</br> ${yAxisLabel}: ${value} `;
+  
+        // // 确保处理最大值等于maxLimit的情况
+        if (
+          values.some(
+            (value) => parseFloat(value) * 1000 == parseFloat(maxLimit) * 1000
+          )
+        ) {
+          frequency[frequency.length - 1]++;
+        }
+        // 1.计算正态分布值
+        const normalDistributionValues = intervals
+          .slice(0, -1)
+          .map((intervalStart, index) => {
+            const intervalEnd = intervals[index + 1];
+            const midpoint = (intervalStart + intervalEnd) / 2;
+  
+            // 使用 Decimal 进行更高精度的计算
+            const midPointDecimal = new Decimal(midpoint);
+            const avgDecimal = new Decimal(scoreBasic.avg);
+            const stdDevDecimal = new Decimal(scoreBasic.stdDev);
+  
+            const exponent = midPointDecimal
+              .minus(avgDecimal)
+              .dividedBy(stdDevDecimal)
+              .pow(2)
+              .negated()
+              .dividedBy(new Decimal(2));
+            const exponentValue = new Decimal(Math.exp(exponent.toNumber())); // 取自然指数
+            const coefficient = new Decimal(1).dividedBy(
+              stdDevDecimal.times(new Decimal(Math.sqrt(2 * Math.PI)))
+            );
+  
+            return coefficient.times(exponentValue).toNumber(); // 返回计算结果
+          });
+        const option = {
+          color: ["rgba(245,0,0,0.6)"],
+          dataZoom: [
+            {
+              type: "inside", // 内置于坐标系中
+              start: 0,
+              end: 100,
+              xAxisIndex: [0],
+            },
+          ],
+          tooltip: {
+            trigger: "axis",
+            axisPointer: {
+              type: "shadow",
+            },
+            formatter: (params) => {
+              // 使用箭头函数来保持 this 的上下文
+              const seriesName = params[0].name; // 系列名称
+              const dataIndex = params[0].dataIndex; // 数据索引
+              const value = params[0].data; // 实际的数据值
+              const xAxisLabel = params[0].axisValueLabel; // x轴的标签
+              const yAxisLabel = params[0].seriesName;
+              // 构建自定义的 tooltip 内容,包含年份
+              return `${xAxisLabel}</br> ${yAxisLabel}: ${value} `;
+            },
           },
-        },
-        legend: {
-          data: [`${that.form.selectedYear}工业生产总值企业数统计`, "正态分布"],
-        },
-        grid: {
-          left: "3%",
-          right: "4%",
-          bottom: "50px",
-          containLabel: true,
-        },
-        xAxis: {
-          type: "category",
-          name: "分布区间",
-          // data: histogramData.map((item) => item.name),
-          data: intervalStrings.map((item) => item.name),
-          axisLabel: {
-            fontSize: 12,
-            rotate: 0,
-            // padding: [0, 0, 0, -200]
+          legend: {
+            data: [`${that.form.selectedYear}工业生产总值企业数统计`, "正态分布"],
           },
-        },
-        yAxis: [
-          {
-            name: "企业数",
-            type: "value",
-            minInterval: 1,
+          grid: {
+            left: "3%",
+            right: "4%",
+            bottom: "50px",
+            containLabel: true,
           },
-          {
-            name: "正态分布",
-            type: "value",
+          xAxis: {
+            type: "category",
+            name: "分布区间",
+            // data: histogramData.map((item) => item.name),
+            data: intervalStrings.map((item) => item.name),
+            axisLabel: {
+              fontSize: 12,
+              rotate: 0,
+              // padding: [0, 0, 0, -200]
+            },
           },
-        ],
-        series: [
-          {
-            name: `${that.form.selectedYear}工业生产总值企业数统计`,
-            type: "bar",
-            barWidth: "30%",
-            itemStyle: {
-              // color: "rgba(245,0,0,0.6)",
-              normal: {
-                color: function (params) {
-                  const value = params.dataIndex; // 获取当前柱子在数据中的索引
-                  let min = parseFloat(intervalStrings[value].min) * 1000;
-                  let max = parseFloat(intervalStrings[value].max) * 1000;
-                  if (newZScore * 1000 >= min && newZScore * 1000 < max) {
-                    return "#ffcc00";
-                  } else if (
-                    newZScore * 1000 == maxLimit * 1000 &&
-                    max == maxLimit * 1000
-                  ) {
-                    return "#ffcc00";
-                  }
-                  return "rgba(245,0,0,0.6)";
-                  // 默认颜色
+          yAxis: [
+            {
+              name: "企业数",
+              type: "value",
+              minInterval: 1,
+            },
+            {
+              name: "正态分布",
+              type: "value",
+            },
+          ],
+          series: [
+            {
+              name: `${that.form.selectedYear}工业生产总值企业数统计`,
+              type: "bar",
+              barWidth: "30%",
+              itemStyle: {
+                // color: "rgba(245,0,0,0.6)",
+                normal: {
+                  color: function (params) {
+                    const value = params.dataIndex; // 获取当前柱子在数据中的索引
+                    let min = parseFloat(intervalStrings[value].min) * 1000;
+                    let max = parseFloat(intervalStrings[value].max) * 1000;
+                    if (newZScore * 1000 >= min && newZScore * 1000 < max) {
+                      return "#ffcc00";
+                    } else if (
+                      newZScore * 1000 == maxLimit * 1000 &&
+                      max == maxLimit * 1000
+                    ) {
+                      return "#ffcc00";
+                    }
+                    return "rgba(245,0,0,0.6)";
+                    // 默认颜色
+                  },
                 },
               },
+              // data: histogramData.map((item) => item.value),
+              data: frequency,
+              label: {
+                show: false, // 将show属性设置为false,去掉柱子上的数字
+              },
             },
-            // data: histogramData.map((item) => item.value),
-            data: frequency,
-            label: {
-              show: false, // 将show属性设置为false,去掉柱子上的数字
-            },
-          },
-          {
-            name: "正态分布",
-            yAxisIndex: 1,
-            type: "line",
-            data: normalDistributionValues,
-            lineStyle: {
-              color: "#1a7cc8",
+            {
+              name: "正态分布",
+              yAxisIndex: 1,
+              type: "line",
+              data: normalDistributionValues,
+              lineStyle: {
+                color: "#1a7cc8",
+              },
+              symbol: "none",
             },
-            symbol: "none",
-          },
-        ],
-      };
-      this.chart.setOption(option);
-      this.chart.on("click", function (param) {
-        if (
-          typeof param.dataIndex === "number" &&
-          param.dataIndex >= 0 &&
-          param.dataIndex < intervalStrings.length
-        ) {
-          let dataIndexValue = intervalStrings[param.dataIndex];
-          const filteredArray = result.filter((item) => {
-            let score = new Decimal(item.score);
-            let max = new Decimal(dataIndexValue.max);
-            let min = new Decimal(dataIndexValue.min);
-            let maxL = new Decimal(maxLimit);
-            const isMaxValEqual = max.equals(maxL);
-            const lowerBoundCheck = score.greaterThan(min) || score.equals(min);
-            const upperBoundCheck = isMaxValEqual
-              ? score.lessThan(max) || score.equals(max)
-              : score.lessThan(max);
-            return lowerBoundCheck && upperBoundCheck;
-          });
-          that.tableData = filteredArray.map((item) => {
-            return {
-              totalIndustrialValue: item.totalIndustrialValue.toFixed(2),
-              enterpriseId: item.name,
-              year: that.form.selectedYear,
-              value: item.score.toFixed(2),
-            };
-          });
-        }
-      });
-    },
-    // 重置表单
-    resetForm() {
-      this.$refs.ruleForm.resetFields();
-      this.calShow = "init";
+          ],
+        };
+        this.chart.setOption(option);
+        this.chart.on("click", function (param) {
+          if (
+            typeof param.dataIndex === "number" &&
+            param.dataIndex >= 0 &&
+            param.dataIndex < intervalStrings.length
+          ) {
+            let dataIndexValue = intervalStrings[param.dataIndex];
+            const filteredArray = result.filter((item) => {
+              let score = new Decimal(item.score);
+              let max = new Decimal(dataIndexValue.max);
+              let min = new Decimal(dataIndexValue.min);
+              let maxL = new Decimal(maxLimit);
+              const isMaxValEqual = max.equals(maxL);
+              const lowerBoundCheck = score.greaterThan(min) || score.equals(min);
+              const upperBoundCheck = isMaxValEqual
+                ? score.lessThan(max) || score.equals(max)
+                : score.lessThan(max);
+              return lowerBoundCheck && upperBoundCheck;
+            });
+            that.tableData = filteredArray.map((item) => {
+              return {
+                totalIndustrialValue: item.totalIndustrialValue.toFixed(2),
+                enterpriseId: item.name,
+                year: that.form.selectedYear,
+                value: item.score.toFixed(2),
+              };
+            });
+          }
+        });
+      },
+      // 重置表单
+      resetForm() {
+        this.$refs.ruleForm.resetFields();
+        this.calShow = "init";
+      },
     },
-  },
-  watch: {},
-};
-</script>
-
-<style scoped>
-.select-container {
-  margin: 10px 0;
-  font-size: 16px; /* 调整字号大小 */
-}
-
-.select-container select {
-  padding: 10px 20px; /* 增加内边距 */
-  margin-right: 10px; /* 增加右边距 */
-  border: 1px solid #121315; /* 蓝色边框 */
-  border-radius: 4px; /* 圆角边框 */
-  background-color: white; /* 背景色 */
-  color: #121315; /* 文字颜色 */
-  font-size: 16px; /* 调整字号大小 */
-  cursor: pointer; /* 鼠标悬停时的指针样式 */
-  outline: none; /* 移除焦点时的轮廓 */
-}
-
-.select-container select:hover {
-  border-color: #1a7cc8; /* 鼠标悬停时的边框颜色 */
-}
-
-.select-container select:focus {
-  border-color: #121315; /* 焦点时的边框颜色 */
-  box-shadow: 0 0 0 2px rgba(64, 159, 255, 0.2); /* 焦点时的阴影效果 */
-}
-</style>
+    watch: {},
+  };
+  </script>
+  
+  <style scoped>
+  .select-container {
+    margin: 10px 0;
+    font-size: 16px; /* 调整字号大小 */
+  }
+  
+  .select-container select {
+    padding: 10px 20px; /* 增加内边距 */
+    margin-right: 10px; /* 增加右边距 */
+    border: 1px solid #121315; /* 蓝色边框 */
+    border-radius: 4px; /* 圆角边框 */
+    background-color: white; /* 背景色 */
+    color: #121315; /* 文字颜色 */
+    font-size: 16px; /* 调整字号大小 */
+    cursor: pointer; /* 鼠标悬停时的指针样式 */
+    outline: none; /* 移除焦点时的轮廓 */
+  }
+  
+  .select-container select:hover {
+    border-color: #1a7cc8; /* 鼠标悬停时的边框颜色 */
+  }
+  
+  .select-container select:focus {
+    border-color: #121315; /* 焦点时的边框颜色 */
+    box-shadow: 0 0 0 2px rgba(64, 159, 255, 0.2); /* 焦点时的阴影效果 */
+  }
+  </style>
+  

+ 648 - 0
src/views/investment/index_backup.vue

@@ -0,0 +1,648 @@
+<template>
+  <!-- 招商 - littlegreen - 补充form和label -->
+  <div
+    :class="className"
+    :style="{ height: '100%', width: width, padding: '20px' }"
+  >
+    <div class="select-container">
+      <el-form
+        :model="form"
+        :rules="rules"
+        ref="ruleForm"
+        style="
+          display: grid;
+          grid-template-columns: 1fr 1fr;
+          align-items: center;
+          grid-gap: 20px;
+        "
+      >
+        <el-form-item
+          label="新增企业月均工业产值"
+          label-width="200px"
+          prop="newMonthValue"
+        >
+          <div style="display: flex; align-items: cente">
+            <el-input
+              v-model.number="form.newMonthValue"
+              placeholder="请输入企业月均工业产值"
+              clearable
+            />
+            <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
+          </div>
+        </el-form-item>
+        <el-form-item label="行业代码" label-width="100px" prop="selectedCode">
+          <el-select v-model="form.selectedCode" style="width: 100%" filterable>
+            <el-option
+              v-for="item in selectedIndustryArray"
+              :key="item.key"
+              :label="item.value"
+              :value="item.key"
+            >
+            </el-option> </el-select
+        ></el-form-item>
+        <el-form-item
+          label="新增企业年实缴税金"
+          label-width="200px"
+          prop="newYearTax"
+        >
+          <!-- <el-input
+            v-model="form.newYearTax"
+            placeholder="请输入企业年实缴税金"
+            clearable
+          /> -->
+          <div style="display: flex; align-items: center">
+            <el-input
+              v-model.number="form.newYearTax"
+              placeholder="请输入企业年实缴税金"
+              clearable
+            />
+            <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
+          </div>
+        </el-form-item>
+        <el-form-item label="年度" style="margin-bottom: 0" label-width="100px" prop="selectedYear">
+          <el-select v-model="form.selectedYear" style="width: 100%">
+            <el-option
+              v-for="item in selectedYearArray"
+              :key="item.key"
+              :label="item.value"
+              :value="item.key"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label-width="100px">
+          <el-button type="primary" size="mini" @click="submit">计算</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetForm"
+            >重置</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </div>
+    <div>
+      <h4 v-show="calShow == 'low'" style="padding: 10px; text-align: center">
+        重新计算后输出:企业新增后比新增前行业得分平均降低{{ rate }}%
+      </h4>
+      <h4 v-show="calShow == 'high'" style="padding: 10px; text-align: center">
+        重新计算后输出:企业新增后比新增前行业得分平均提高{{ rate }}%
+      </h4>
+      <h4 v-show="calShow == 'same'" style="padding: 10px; text-align: center">
+        重新计算后输出:企业新增后与新增前行业得分平均一致
+      </h4>
+    </div>
+    <div ref="chart" :style="{ height: height, width: width }"></div>
+    <el-table :data="tableData" border style="width: 100%">
+      <el-table-column prop="year" label="年度" width="200"> </el-table-column>
+      <el-table-column prop="enterpriseId" label="企业ID"></el-table-column>
+      <el-table-column
+        prop="totalIndustrialValue"
+        label="企业月均工业产值"
+        width="200"
+      ></el-table-column>
+      <el-table-column
+        prop="value"
+        label="Z-score得分"
+        width="200"
+      ></el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+import { listAllIndustry } from "@/api/industry/industry"; // 导入行业数据的接口
+import { listAllIndustry_run } from "@/api/industry_run/industry_run"; // 导入行业数据的接口
+require("echarts/theme/macarons"); // echarts theme
+import resize from "@/views/dashboard/mixins/resize";
+import { Decimal } from "decimal.js";
+import { getIndexData } from "@/api/home";
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: "chart",
+    },
+    width: {
+      type: String,
+      default: "100%",
+    },
+    height: {
+      type: String,
+      default: "400px",
+    },
+  },
+  data() {
+    return {
+      selectedYearArray: [],
+      calShow: "init",
+      rate: null,
+      chart: null,
+      chartData: [],
+      industryData: [],
+      industryMap: new Map(),
+      selectedDataKey: "totalIndustrialValueScore", // 默认选择的字段
+      form: {
+        selectedCode: null,
+        newMonthValue: null,
+        newYearTax: null,
+        selectedYear: null
+      },
+      rules: {
+        selectedCode: [
+          { required: true, message: "请选择行业", trigger: "blur" },
+        ],
+        newMonthValue: [
+          {
+            required: true,
+            message: "请输入企业月均工业产值",
+            trigger: "blur",
+          },
+          { type: "number", message: "企业月均工业产值必须为数字" },
+        ],
+        newYearTax: [
+          {
+            type: "number",
+            message: "企业年实缴税金必须为数字",
+            trigger: "blur",
+          },
+        ],
+        selectedYear: [
+          { required: true, message: "请选择年度", trigger: "blur" },
+        ]
+      },
+      selectedIndustryArray: [],
+      selectedYear: null,
+      selectedRange: 0.1, // 不能为 0, - littlegreen - 固定0.1
+      // littlegreen - 检测区间 和 表格数据
+      detectMin: null,
+      detectMax: null,
+      tableData: [],
+      scoreData: [],
+    };
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.fetchData();
+    });
+  },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose();
+    }
+  },
+  methods: {
+    // 拉取初始数据
+    async fetchData() {
+      const that = this;
+      // 获得所有行业
+      // that.selectedYear = new Date().getUTCFullYear() + "";
+      await listAllIndustry()
+        .then((res) => {
+          if (res && res?.rows) {
+            that.selectedIndustryArray = res.rows.map((item) => {
+              return {
+                key: item.code,
+                value: item.code + item.industryName,
+              };
+            });
+          }
+        })
+        .catch((error) => {
+          console.error("Error fetching data:", error);
+        });
+
+      await getIndexData({
+        year: 0,
+      })
+        .then((res) => {
+          if (res && res?.rows) {
+            that.selectedYearArray = res.rows[0].years.map((v) => {
+              return {
+                key: v,
+                value: v,
+              };
+            });
+          }
+        })
+        .catch((error) => {
+          console.error("Error fetching data:", error);
+        });
+    },
+    // 提交表单
+    submit() {
+      this.$refs.ruleForm.validate((valid) => {
+        if (valid) {
+          this.handleData();
+        } else {
+          console.error("error submit!!");
+          return false;
+        }
+      });
+    },
+    // 处理数据
+    handleData() {
+      // 1.拿当前年份和code的企业运行数据过来
+      // 2.计算每个企业的z-score
+      // 3.画图
+      const that = this;
+      listAllIndustry_run({
+        code: that.form.selectedCode,
+        year: that.form.selectedYear,
+      })
+        .then((res) => {
+          if (res && res.rows) {
+            that.scoreData = res.rows;
+            that.initChart();
+          }
+        })
+        .catch((error) => {
+          console.error("Error fetching data:", error);
+        });
+    },
+    initChart() {
+      if (this.chart) {
+        this.chart.dispose();
+      }
+      this.chart = echarts.init(this.$refs.chart, "macarons");
+      this.updateChart();
+    },
+    updateChart() {
+      const that = this;
+      if (!this.chart) {
+        return;
+      }
+      let newMonthValue = new Decimal(that.form.newMonthValue).toNumber();
+      let total = [newMonthValue]; //总值
+      const result = Object.values(
+        that.scoreData.reduce((acc, item) => {
+          const key = item.enterpriseName; // 根据企业名称分组
+          let totalIndustrialValue = new Decimal(item.totalIndustrialValue);
+          if (!acc[key]) {
+            acc[key] = {
+              name: key,
+              data: [],
+              totalValue: new Decimal(0),
+              count: 0,
+            }; // 创建对象并初始化
+          }
+
+          acc[key].data.push(item); // 添加到对应的类别中
+          acc[key].totalValue = acc[key].totalValue.plus(totalIndustrialValue); // 累加 totalIndustrialValue
+          acc[key].count++; // 企业数 +1
+          return acc;
+        }, {})
+      ).map(({ name, data, totalValue, count }) => {
+        const totalIndustrialValue = totalValue.dividedBy(count).toNumber(); // 计算均值
+        total.push(totalIndustrialValue);
+        return { name, data, totalIndustrialValue }; // 返回结果
+      });
+      result.push({
+        name: "新企业",
+        data: [],
+        totalIndustrialValue: newMonthValue,
+      });
+
+      // littlegreen --计算增加新企业之后工业产值变化 计算全体企业 totalIndustrialValue 均值
+      const totalValues = result.map(
+        (e) => new Decimal(e.totalIndustrialValue)
+      );
+      const overallMean = totalValues
+        .reduce((sum, value) => sum.plus(value), new Decimal(0))
+        .dividedBy(totalValues.length);
+
+      // 计算不包括“新企业”的均值
+      const filteredValues = result
+        .filter((e) => e.name !== "新企业")
+        .map((e) => new Decimal(e.totalIndustrialValue));
+
+      const filteredMean = filteredValues
+        .reduce((sum, value) => sum.plus(value), new Decimal(0))
+        .dividedBy(filteredValues.length);
+      const relativeChange = overallMean.minus(filteredMean).dividedBy(filteredMean).mul(new Decimal(100));
+      // 显示增加/降低/一致
+      that.calShow = relativeChange.greaterThan(0) ? "high" : (relativeChange.lessThan(0)? "low" : "same")
+      // 增加的比率
+      that.rate = relativeChange.abs().toNumber().toFixed(2)
+
+      // 获取基础数据:最大值,最小值,平均值,标准差
+      function getBebeQ(numbers, digit = 2) {
+        let sum = numbers.reduce(
+          (acc, num) => acc.add(new Decimal(num)),
+          new Decimal(0)
+        );
+
+        let max = Math.max.apply(null, numbers);
+        let min = Math.min.apply(null, numbers);
+
+        // 平均值
+        let mean = sum.dividedBy(numbers.length);
+
+        // 计算每个数与均值的差的平方
+        const squaredDiffs = numbers.map((num) => {
+          const diff = new Decimal(num).minus(mean);
+          return diff.pow(2);
+        });
+
+        // 计算平方差的均值
+        const sumOfSquaredDiffs = squaredDiffs.reduce(
+          (acc, diff) => acc.add(diff),
+          new Decimal(0)
+        );
+
+        const variance = sumOfSquaredDiffs.dividedBy(numbers.length);
+
+        // 开平方得到标准差
+        const standardDeviation = variance.sqrt();
+
+        // 向上取整到最近的 0.1
+        const ceilingRoundedMax = Math.ceil(max * 10) / 10;
+
+        // 向下取整到最近的 0.1
+        const floorRoundedMin = Math.floor(min * 10) / 10;
+
+        return {
+          max: ceilingRoundedMax,
+          min: floorRoundedMin,
+          avg: parseFloat(mean.toNumber().toFixed(digit)) || 0,
+          stdDev: parseFloat(standardDeviation.toNumber().toFixed(digit)),
+        };
+      }
+
+      // 示例数据
+      const betaData = getBebeQ(total);
+      let newZScore;
+      const values = result.map((item) => {
+        let num = item.totalIndustrialValue;
+        const zScore = new Decimal(num)
+          .minus(betaData.avg)
+          .dividedBy(betaData.stdDev);
+        let scoreNum = zScore.toNumber();
+        if (new Decimal(num).equals(new Decimal(that.form.newMonthValue))) {
+          newZScore = scoreNum;
+        }
+        item.score = scoreNum;
+        return scoreNum;
+      });
+      // 计算 z-score 的基础数据
+      const scoreBasic = getBebeQ(values);
+      const center = new Decimal(scoreBasic.avg); // 确保 center 是 Decimal 类型
+      const interval = new Decimal(0.1);
+
+      // 使用 Decimal 来处理 minLimit 和 maxLimit
+      let minLimit = new Decimal(scoreBasic.min); // 向下取整到最近的0.1
+      let maxLimit = new Decimal(scoreBasic.max); // 向上取整到最近的0.1
+
+      // 确保 minLimit 和 maxLimit 关于 center 对称
+      if (!center.minus(minLimit).equals(maxLimit.minus(center))) {
+        const distanceToCenter = center
+          .minus(minLimit)
+          .gt(maxLimit.minus(center))
+          ? center.minus(minLimit)
+          : maxLimit.minus(center);
+
+        maxLimit = center.plus(distanceToCenter); // 更新 maxLimit 保持对称
+        minLimit = center.minus(distanceToCenter); // 更新 minLimit 保持对称
+      }
+
+      const intervals = [];
+      // 乘以1000 是将小数变成整数去计算,小数计算会有误差
+      for (
+        let i = minLimit * 1000;
+        i <= maxLimit * 1000;
+        i += interval * 1000
+      ) {
+        intervals.push(parseFloat((i / 1000).toFixed(2)));
+      }
+      // // 计算每个间隔的频次
+      const frequency = new Array(intervals.length - 1).fill(0); // 初始化频次数组
+
+      let intervalArr = intervals.slice(0, -1);
+      const intervalStrings = [];
+      for (let i = 0; i < intervalArr.length; i++) {
+        const start = intervalArr[i].toFixed(1); // 保留一位小数
+        const end = ((intervalArr[i] * 1000 + interval * 1000) / 1000).toFixed(
+          1
+        ); // 保留一位小数
+        intervalStrings.push({
+          name: `${start}-${end}`,
+          max: end,
+          min: start,
+        }); // 构建区间字符串
+      }
+
+      values.forEach((value) => {
+        for (let j = 0; j < intervalStrings.length; j++) {
+          // 保证包含右边界
+          let v = parseFloat(value) * 1000;
+          if (
+            v >= parseFloat(intervalStrings[j].min) * 1000 &&
+            v < parseFloat(intervalStrings[j].max) * 1000
+          ) {
+            frequency[j]++;
+            break; // 找到对应区间后可以跳出循环
+          }
+        }
+      });
+
+      // // 确保处理最大值等于maxLimit的情况
+      if (
+        values.some(
+          (value) => parseFloat(value) * 1000 == parseFloat(maxLimit) * 1000
+        )
+      ) {
+        frequency[frequency.length - 1]++;
+      }
+      // 1.计算正态分布值
+      const normalDistributionValues = intervals
+        .slice(0, -1)
+        .map((intervalStart, index) => {
+          const intervalEnd = intervals[index + 1];
+          const midpoint = (intervalStart + intervalEnd) / 2;
+
+          // 使用 Decimal 进行更高精度的计算
+          const midPointDecimal = new Decimal(midpoint);
+          const avgDecimal = new Decimal(scoreBasic.avg);
+          const stdDevDecimal = new Decimal(scoreBasic.stdDev);
+
+          const exponent = midPointDecimal
+            .minus(avgDecimal)
+            .dividedBy(stdDevDecimal)
+            .pow(2)
+            .negated()
+            .dividedBy(new Decimal(2));
+          const exponentValue = new Decimal(Math.exp(exponent.toNumber())); // 取自然指数
+          const coefficient = new Decimal(1).dividedBy(
+            stdDevDecimal.times(new Decimal(Math.sqrt(2 * Math.PI)))
+          );
+
+          return coefficient.times(exponentValue).toNumber(); // 返回计算结果
+        });
+      const option = {
+        color: ["rgba(245,0,0,0.6)"],
+        dataZoom: [
+          {
+            type: "inside", // 内置于坐标系中
+            start: 0,
+            end: 100,
+            xAxisIndex: [0],
+          },
+        ],
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow",
+          },
+          formatter: (params) => {
+            // 使用箭头函数来保持 this 的上下文
+            const seriesName = params[0].name; // 系列名称
+            const dataIndex = params[0].dataIndex; // 数据索引
+            const value = params[0].data; // 实际的数据值
+            const xAxisLabel = params[0].axisValueLabel; // x轴的标签
+            const yAxisLabel = params[0].seriesName;
+            // 构建自定义的 tooltip 内容,包含年份
+            return `${xAxisLabel}</br> ${yAxisLabel}: ${value} `;
+          },
+        },
+        legend: {
+          data: [`${that.form.selectedYear}工业生产总值企业数统计`, "正态分布"],
+        },
+        grid: {
+          left: "3%",
+          right: "4%",
+          bottom: "50px",
+          containLabel: true,
+        },
+        xAxis: {
+          type: "category",
+          name: "分布区间",
+          // data: histogramData.map((item) => item.name),
+          data: intervalStrings.map((item) => item.name),
+          axisLabel: {
+            fontSize: 12,
+            rotate: 0,
+            // padding: [0, 0, 0, -200]
+          },
+        },
+        yAxis: [
+          {
+            name: "企业数",
+            type: "value",
+            minInterval: 1,
+          },
+          {
+            name: "正态分布",
+            type: "value",
+          },
+        ],
+        series: [
+          {
+            name: `${that.form.selectedYear}工业生产总值企业数统计`,
+            type: "bar",
+            barWidth: "30%",
+            itemStyle: {
+              // color: "rgba(245,0,0,0.6)",
+              normal: {
+                color: function (params) {
+                  const value = params.dataIndex; // 获取当前柱子在数据中的索引
+                  let min = parseFloat(intervalStrings[value].min) * 1000;
+                  let max = parseFloat(intervalStrings[value].max) * 1000;
+                  if (newZScore * 1000 >= min && newZScore * 1000 < max) {
+                    return "#ffcc00";
+                  } else if (
+                    newZScore * 1000 == maxLimit * 1000 &&
+                    max == maxLimit * 1000
+                  ) {
+                    return "#ffcc00";
+                  }
+                  return "rgba(245,0,0,0.6)";
+                  // 默认颜色
+                },
+              },
+            },
+            // data: histogramData.map((item) => item.value),
+            data: frequency,
+            label: {
+              show: false, // 将show属性设置为false,去掉柱子上的数字
+            },
+          },
+          {
+            name: "正态分布",
+            yAxisIndex: 1,
+            type: "line",
+            data: normalDistributionValues,
+            lineStyle: {
+              color: "#1a7cc8",
+            },
+            symbol: "none",
+          },
+        ],
+      };
+      this.chart.setOption(option);
+      this.chart.on("click", function (param) {
+        if (
+          typeof param.dataIndex === "number" &&
+          param.dataIndex >= 0 &&
+          param.dataIndex < intervalStrings.length
+        ) {
+          let dataIndexValue = intervalStrings[param.dataIndex];
+          const filteredArray = result.filter((item) => {
+            let score = new Decimal(item.score);
+            let max = new Decimal(dataIndexValue.max);
+            let min = new Decimal(dataIndexValue.min);
+            let maxL = new Decimal(maxLimit);
+            const isMaxValEqual = max.equals(maxL);
+            const lowerBoundCheck = score.greaterThan(min) || score.equals(min);
+            const upperBoundCheck = isMaxValEqual
+              ? score.lessThan(max) || score.equals(max)
+              : score.lessThan(max);
+            return lowerBoundCheck && upperBoundCheck;
+          });
+          that.tableData = filteredArray.map((item) => {
+            return {
+              totalIndustrialValue: item.totalIndustrialValue.toFixed(2),
+              enterpriseId: item.name,
+              year: that.form.selectedYear,
+              value: item.score.toFixed(2),
+            };
+          });
+        }
+      });
+    },
+    // 重置表单
+    resetForm() {
+      this.$refs.ruleForm.resetFields();
+      this.calShow = "init";
+    },
+  },
+  watch: {},
+};
+</script>
+
+<style scoped>
+.select-container {
+  margin: 10px 0;
+  font-size: 16px; /* 调整字号大小 */
+}
+
+.select-container select {
+  padding: 10px 20px; /* 增加内边距 */
+  margin-right: 10px; /* 增加右边距 */
+  border: 1px solid #121315; /* 蓝色边框 */
+  border-radius: 4px; /* 圆角边框 */
+  background-color: white; /* 背景色 */
+  color: #121315; /* 文字颜色 */
+  font-size: 16px; /* 调整字号大小 */
+  cursor: pointer; /* 鼠标悬停时的指针样式 */
+  outline: none; /* 移除焦点时的轮廓 */
+}
+
+.select-container select:hover {
+  border-color: #1a7cc8; /* 鼠标悬停时的边框颜色 */
+}
+
+.select-container select:focus {
+  border-color: #121315; /* 焦点时的边框颜色 */
+  box-shadow: 0 0 0 2px rgba(64, 159, 255, 0.2); /* 焦点时的阴影效果 */
+}
+</style>