<template>
  <div class="apaas-custom-check-data custom-page">
    <!-- Tab切换区域 -->
    <div class="tab-header">
      <el-tabs v-model="activeTab" @tab-click="handleTabClick">
        <el-tab-pane label="机型参数查询" name="model-query"></el-tab-pane>
        <el-tab-pane label="对标报告查询" name="benchmark-report"></el-tab-pane>
        <el-tab-pane label="统计分析" name="statistics"></el-tab-pane>
      </el-tabs>
    </div>

    <!-- Tab组件内容 -->
    <ModelQuery v-show="activeTab === 'model-query'" />
    <BenchmarkReport v-show="activeTab === 'benchmark-report'" />
    <div v-show="activeTab === 'statistics'" class="statistics-tab tab-content">
      <!-- 顶部筛选区域 -->
      <!-- <div class="page-search-panel check-data-panel">
        <div class="panel-header">
          <h2 class="panel-title">
            查询分析
          </h2>
          <div class="header-right">
            <span class="favorites-label">我的常用:</span>
            <el-select v-model="favoritesValue" placeholder="请选择" class="favorites-select">
              <el-option
                v-for="item in favoritesOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
            <el-button class="update-favorite-button" @click="handleUpdateFavorite">
              更新常用
            </el-button>
            <el-button type="primary" class="add-favorite-button" @click="handleAddFavorite">
              新增常用
            </el-button>
          </div>
        </div>
      </div> -->

      <div class="page-search-panel">
        <div class="search-fields">
          <div class="search-row">
            <div class="search-field">
              <span class="field-label">产品型号</span>
              <el-select
                v-model="searchPanelValue.modelName"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterModelNameOptions"
                @visible-change="handleFilterVisibleChange('modelName', $event)"
                @change="handleFilterChange('modelName')"
              >
                <el-option
                  v-for="item in filteredOptions.modelName"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
            <div class="search-field">
              <span class="field-label">状态代号</span>
              <el-select
                v-model="searchPanelValue.productNumber"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterProductNumberOptions"
                @visible-change="handleFilterVisibleChange('productNumber', $event)"
                @change="handleFilterChange('productNumber')"
              >
                <el-option
                  v-for="item in filteredOptions.productNumber"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
            <div class="search-field">
              <span class="field-label">项目名称</span>
              <el-select
                v-model="searchPanelValue.projectName"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterProjectNameOptions"
                @visible-change="handleFilterVisibleChange('projectName', $event)"
                @change="handleFilterChange('projectName')"
              >
                <el-option
                  v-for="item in filteredOptions.projectName"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
            <div class="search-field">
              <span class="field-label">板块</span>
              <el-select
                v-model="searchPanelValue.plate"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterPlateOptions"
                @visible-change="handleFilterVisibleChange('plate', $event)"
                @change="handleFilterChange('plate')"
              >
                <el-option
                  v-for="item in filteredOptions.plate"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
          </div>
          <div class="search-row">
            <div class="search-field">
              <span class="field-label">平台</span>
              <el-select
                v-model="searchPanelValue.platform"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterPlatformOptions"
                @visible-change="handleFilterVisibleChange('platform', $event)"
                @change="handleFilterChange('platform')"
              >
                <el-option
                  v-for="item in filteredOptions.platform"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
            <div class="search-field">
              <span class="field-label">系列</span>
              <el-select
                v-model="searchPanelValue.series"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterSeriesOptions"
                @visible-change="handleFilterVisibleChange('series', $event)"
                @change="handleFilterChange('series')"
              >
                <el-option
                  v-for="item in filteredOptions.series"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
            <div class="search-field">
              <span class="field-label">燃烧类型</span>
              <el-select
                v-model="searchPanelValue.burnType"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterBurnTypeOptions"
                @visible-change="handleFilterVisibleChange('burnType', $event)"
                @change="handleFilterChange('burnType')"
              >
                <el-option
                  v-for="item in filteredOptions.burnType"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
            <div class="search-field">
              <span class="field-label">排放</span>
              <el-select
                v-model="searchPanelValue.emission"
                placeholder="请选择"
                clearable
                filterable
                multiple
                collapse-tags
                :filter-method="filterEmissionOptions"
                @visible-change="handleFilterVisibleChange('emission', $event)"
                @change="handleFilterChange('emission')"
              >
                <el-option
                  v-for="item in filteredOptions.emission"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
          </div>
          <div class="search-row">
            <div class="search-field range-field">
              <span class="field-label">排量</span>
              <div class="range-input-group">
                <el-input
                  v-model="searchPanelValue.engineCapacityMin"
                  placeholder="请输入"
                  class="range-input"
                  @blur="handleEngineCapacityBlur"
                />
                <span class="range-separator">~</span>
                <el-input
                  v-model="searchPanelValue.engineCapacityMax"
                  placeholder="请输入"
                  class="range-input"
                  @blur="handleEngineCapacityBlur"
                />
              </div>
            </div>
            <div class="search-actions">
              <el-button type="primary" @click="handleSearch">
                查询
              </el-button>
              <el-button @click="resetSearch">
                重置
              </el-button>
            </div>
          </div>
        </div>
      </div>

      <!-- 常用功能行 -->
      <div class="favorites-panel">
        <div class="header-right">
          <span class="favorites-label">我的常用:</span>
          <el-select
            v-model="favoritesValue"
            placeholder="请选择"
            class="favorites-select"
            clearable
            @change="handleFavoriteChange"
          >
            <el-option
              v-for="item in favoritesOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-button class="update-favorite-button" @click="handleUpdateFavorite">
            更新常用
          </el-button>
          <el-button type="primary" class="add-favorite-button" :disabled="chartList.length === 0" @click="handleAddFavorite">
            新增常用
          </el-button>
        </div>
      </div>

      <!-- 图表管理区域（没有图表时显示） -->
      <div v-if="chartList.length === 0" class="chart-management-panel">
        <el-button type="primary" @click="handleAddChart">
          新增图表
        </el-button>
      </div>

      <!-- 悬浮框（有图表时显示） -->
      <div
        v-if="chartList.length > 0"
        class="floating-panel"
        :class="{ expanded: floatingPanelExpanded }"
      >
        <div class="floating-panel-toggle" @click="toggleFloatingPanel">
          <i :class="floatingPanelExpanded ? 'el-icon-close' : 'el-icon-menu'"></i>
        </div>
        <div v-if="floatingPanelExpanded" class="floating-panel-content">
          <el-button type="primary" size="small" @click="handleAddChart">
            <i class="el-icon-plus"></i>
            新增
          </el-button>
          <el-button size="small" @click="handleClearAllCharts">
            <i class="el-icon-delete"></i>
            清空
          </el-button>
          <el-button size="small" @click="scrollToTop">
            <i class="el-icon-top"></i>
            回到顶部
          </el-button>
        </div>
      </div>

      <!-- 图表区域列表 -->
      <div v-if="chartList.length == 0" class="chart-area empty-chart-area">
      </div>
      <div v-for="(chart, index) in chartList" :key="chart.id" class="chart-area">
        <div class="chart-header">
          <div class="chart-title-section">
            <span v-if="!chart.isEditingTitle" class="chart-title" @click="startEditTitle(index)">{{
              chart.title
            }}</span>
            <el-input
              v-else
              :ref="`titleInput-${index}`"
              v-model="chart.title"
              class="title-input"
              @blur="chart.isEditingTitle = false"
              @keyup.enter.native="chart.isEditingTitle = false"
            />
            <i class="el-icon-edit title-edit-icon" @click="startEditTitle(index)"></i>
          </div>
          <div class="chart-header-right">
            <div class="download-button" @click="handleDownloadChart(index)">
              <i class="el-icon-download"></i>
              <span>下载</span>
            </div>
            <div class="delete-button" @click="handleDeleteChart(index)">
              <i class="el-icon-delete"></i>
              <span>删除</span>
            </div>
          </div>
        </div>

        <div class="chart-config">
          <div class="config-item">
            <span class="config-label">图表类型:</span>
            <el-select v-model="chart.chartType" @change="updateChart(index)">
              <el-option label="散点图" value="scatter" />
              <el-option label="折线图" value="line" />
              <el-option label="柱状图" value="bar" />
            </el-select>
          </div>
          <div class="config-item">
            <span class="config-label">X轴:</span>
            <el-select v-model="chart.xAxis" @change="updateChart(index)">
              <el-option
                v-for="option in xAxisOptions"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
          </div>
          <div class="config-item canshu">
            <span class="config-label">Y轴(参数):</span>
            <el-select
              :key="`y-axis-param-${chart.id}`"
              v-model="chart.yAxisParam"
              filterable
              multiple
              collapse-tags
              clearable
              placeholder="请选择或搜索参数"
              class="y-axis-param-select"
              :filter-method="handleFilterYAxisParam"
              @change="updateChart(index)"
            >
              <el-option
                v-for="option in filteredYAxisParamOptions"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
          </div>
          <div class="config-item">
            <span class="config-label">Y轴(公式):</span>
            <el-select
              v-model="chart.yAxisFormula"
              clearable
              @change="handleFormulaSelectChange(index)"
            >
              <el-option
                v-for="formula in savedFormulas"
                :key="formula.id"
                :label="formula.name"
                :value="formula.id"
              />
            </el-select>
            <el-button type="primary" size="small" @click="handleEditFormula(index)">
              添加/修改公式
            </el-button>
          </div>
          <div v-if="chart.chartType !== 'pie'" class="config-item">
            <span class="config-label">Y轴范围:</span>
            <el-input
              v-model.number="chart.yAxisMin"
              placeholder="最小值"
              class="y-axis-range-input"
              @blur="updateChart(index)"
            />
            <span class="range-separator">~</span>
            <el-input
              v-model.number="chart.yAxisMax"
              placeholder="最大值"
              class="y-axis-range-input"
              @blur="updateChart(index)"
            />
          </div>
          <div v-if="chart.chartType !== 'pie'" class="config-item">
            <span class="config-label">坐标点:</span>
            <el-input
              v-model.number="chart.customPointX"
              :placeholder="getCustomPointXPlaceholder(chart)"
              class="y-axis-range-input"
              @blur="updateChart(index)"
            />
            <span class="range-separator">,</span>
            <el-input
              v-model.number="chart.customPointY"
              placeholder="Y坐标(百分比)"
              class="y-axis-range-input"
              @blur="updateChart(index)"
            />
          </div>
        </div>

        <div class="chart-wrapper">
          <div
            :ref="`chartContainer-${index}`"
            class="chart-container"
            :style="{ height: chart.chartHeight + 'px' }"
          ></div>
          <div class="chart-resize-handle" @mousedown="startResize(index, $event)"></div>
        </div>
      </div>

      <!-- 添加机型弹窗 -->
      <el-dialog
        title="选择机型"
        :visible.sync="addModelDialogVisible"
        width="900px"
        append-to-body
        @close="handleAddModelDialogClose"
      >
        <div class="model-select-dialog">
          <el-transfer
            v-model="transferSelectedKeys"
            :data="transferData"
            :titles="['可选机型', '已选机型']"
            :button-texts="['移除', '添加']"
            :format="{
              noChecked: '${total}',
              hasChecked: '${checked}/${total}'
            }"
            filterable
            :filter-method="filterTransferMethod"
            filter-placeholder="请输入搜索关键词"
            style="text-align: left;"
            @change="handleTransferChange"
          >
            <span slot-scope="{ option }" class="transfer-item">
              <span class="transfer-item-label">{{ option.label }}</span>
            </span>
          </el-transfer>
        </div>
        <span slot="footer" class="dialog-footer">
          <el-button @click="handleAddModelDialogClose">取消</el-button>
          <el-button type="primary" :loading="loadingModelDetail" @click="handleConfirmAddModel">
            确定
          </el-button>
        </span>
      </el-dialog>

      <!-- 公式设置弹窗 -->
      <el-dialog
        :title="currentFormulaId ? '修改公式' : '添加公式'"
        :visible.sync="formulaDialogVisible"
        width="800px"
        :close-on-click-modal="true"
        :modal="false"
        class="formula-dialog"
      >
        <div class="formula-dialog-content">
          <el-form :model="formulaFormData" label-width="100px">
            <el-form-item label="公式名称:" required>
              <el-input
                v-model="formulaFormData.name"
                placeholder="请输入公式名称"
                maxlength="50"
                show-word-limit
              />
            </el-form-item>
            <el-form-item label="选择参数:" required>
              <el-select
                v-model="formulaFormData.selectedParams"
                placeholder="请选择参数（最多5个）"
                multiple
                filterable
                collapse-tags
                :max-collapse-tags="3"
                style="width: 100%"
                @change="handleSelectedParamsChange"
              >
                <el-option
                  v-for="opt in yAxisParamOptions"
                  :key="opt.value"
                  :label="opt.label"
                  :value="opt.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="已选参数:" v-if="formulaFormData.availableParams.length > 0">
              <div class="selected-params-display">
                <div
                  v-for="param in formulaFormData.availableParams"
                  :key="param.value"
                  class="selected-param-tag"
                >
                  {{ param.label }}
                </div>
              </div>
            </el-form-item>
            <el-form-item label="公式构建:">
              <div class="formula-builder">
                <!-- 帮助提示 -->
                <div class="builder-help">
                  <el-popover
                    placement="top"
                    width="300"
                    trigger="click"
                    popper-class="formula-help-popover"
                  >
                    <div class="help-content">
                      <p>选中的参数或者也通过手动输入数字，通过拖动到预览区域形成公式</p>
                    </div>
                    <el-button slot="reference" type="text" size="small" class="help-button">
                      <i class="el-icon-question"></i>
                      帮助
                    </el-button>
                  </el-popover>
                </div>
                <!-- 可拖动区域：参数、运算符、括号、数字 -->
                <div class="draggable-items">
                  <div class="items-section">
                    <div class="section-title">
                      参数
                      <span class="section-tip">（可重复使用）</span>
                    </div>
                    <div class="items-container">
                      <div
                        v-for="param in formulaFormData.availableParams"
                        :key="param.value"
                        class="draggable-item param-item"
                        :data-type="'param'"
                        :data-value="param.value"
                        :data-label="param.label"
                        draggable="true"
                        @dragstart="handleDragStart($event, 'param', param.value, param.label)"
                        @dragend="handleDragEnd($event)"
                      >
                        {{ param.label }}
                      </div>
                      <div v-if="formulaFormData.availableParams.length === 0" class="empty-tip">
                        请先选择参数
                      </div>
                    </div>
                  </div>
                  <div class="items-section">
                    <div class="section-title">运算符</div>
                    <div class="items-container">
                      <div
                        v-for="op in formulaOperators"
                        :key="op.value"
                        class="draggable-item operator-item"
                        :data-type="'operator'"
                        :data-value="op.value"
                        :data-label="op.label"
                        draggable="true"
                        @dragstart="handleDragStart($event, 'operator', op.value, op.label)"
                        @dragend="handleDragEnd($event)"
                      >
                        {{ op.label }}
                      </div>
                    </div>
                  </div>
                  <div class="items-section">
                    <div class="section-title">括号</div>
                    <div class="items-container">
                      <div
                        class="draggable-item bracket-item"
                        :data-type="'bracket'"
                        :data-value="'('"
                        :data-label="'('"
                        draggable="true"
                        @dragstart="handleDragStart($event, 'bracket', '(', '(')"
                        @dragend="handleDragEnd($event)"
                      >
                        (
                      </div>
                      <div
                        class="draggable-item bracket-item"
                        :data-type="'bracket'"
                        :data-value="')'"
                        :data-label="')'"
                        draggable="true"
                        @dragstart="handleDragStart($event, 'bracket', ')', ')')"
                        @dragend="handleDragEnd($event)"
                      >
                        )
                      </div>
                    </div>
                  </div>
                  <div class="items-section">
                    <div class="items-container number-section-container">
                      <div class="number-input-row">
                        <span class="number-label">数字：</span>
                        <el-input-number
                          v-model="formulaFormData.inputNumber"
                          :precision="2"
                          :step="1"
                          :min="0"
                          size="small"
                          style="width: 120px;"
                          placeholder="输入数字"
                        />
                        <el-button
                          type="primary"
                          size="small"
                          :disabled="formulaFormData.inputNumber === null || formulaFormData.inputNumber === ''"
                          @click="addNumberToBuilder"
                        >
                          添加到构建区
                        </el-button>
                      </div>
                      <div
                        v-if="formulaFormData.recentNumbers.length > 0"
                        class="recent-numbers"
                      >
                        <div
                          v-for="(num, index) in formulaFormData.recentNumbers"
                          :key="index"
                          class="draggable-item number-item"
                          :data-type="'number'"
                          :data-value="String(num)"
                          :data-label="String(num)"
                          draggable="true"
                          @dragstart="handleDragStart($event, 'number', String(num), String(num))"
                          @dragend="handleDragEnd($event)"
                        >
                          {{ num }}
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <!-- 预览区域：拖放构建公式 -->
                <div class="formula-preview-area">
                  <div class="preview-title">公式预览</div>
                  <div
                    class="preview-container"
                    :class="{ 'drag-over': isDraggingOver }"
                    @drop="handleDrop"
                    @dragover.prevent
                    @dragenter.prevent="handleDragEnter"
                    @dragleave="handleDragLeave"
                  >
                    <div
                      v-if="formulaFormData.formulaItems.length === 0"
                      class="empty-preview"
                    >
                      请将参数、运算符、括号或数字拖拽到此处构建公式
                    </div>
                    <div
                      v-for="(item, index) in formulaFormData.formulaItems"
                      :key="index"
                      class="preview-item"
                      :class="{
                        'is-param': item.type === 'param',
                        'is-operator': item.type === 'operator',
                        'is-bracket': item.type === 'bracket',
                        'is-number': item.type === 'number',
                        'is-dragging': draggingPreviewIndex === index,
                        'drag-over': dragOverPreviewIndex === index && draggingPreviewIndex !== -1
                      }"
                      draggable="true"
                      :data-index="index"
                      @dragstart="handlePreviewDragStart($event, index)"
                      @dragover.prevent="handlePreviewDragOver($event, index)"
                      @dragenter.prevent="handlePreviewDragEnter($event, index)"
                      @dragleave="handlePreviewDragLeave($event)"
                      @drop="handlePreviewDrop($event, index)"
                      @dragend="handlePreviewDragEnd($event)"
                    >
                      <span class="item-content">{{ item.label }}</span>
                      <i class="el-icon-close remove-btn" @click="removeFormulaItem(index)"></i>
                    </div>
                  </div>
                  <div class="preview-actions">
                    <el-button size="small" @click="clearFormula">清空</el-button>
                  </div>
                </div>
              </div>
            </el-form-item>
          </el-form>
        </div>
        <span slot="footer" class="dialog-footer">
          <el-button @click="handleFormulaDialogClose">
            取消
          </el-button>
          <el-button type="primary" :disabled="!isFormulaValid" @click="handleSaveFormula">
            确定
          </el-button>
        </span>
      </el-dialog>

      <!-- 新增常用弹窗 -->
      <el-dialog
        title="新增常用"
        :visible.sync="addFavoriteDialogVisible"
        width="500px"
        append-to-body
        @close="handleAddFavoriteDialogClose"
      >
        <el-form
          ref="addFavoriteForm"
          :model="addFavoriteFormData"
          :rules="addFavoriteFormRules"
          label-width="100px"
        >
          <el-form-item label="常用名称" prop="commonName">
            <el-input
              v-model="addFavoriteFormData.commonName"
              placeholder="请输入常用名称"
              maxlength="50"
              show-word-limit
            />
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="handleAddFavoriteDialogClose">
            取消
          </el-button>
          <el-button type="primary" :loading="savingFavorite" @click="handleConfirmAddFavorite">
            确定
          </el-button>
        </div>
      </el-dialog>
    </div>
    <AnalysisReport v-if="activeTab === 'analysis-report'" />
  </div>
</template>

<script>
import * as echarts from 'echarts'
import api from '@/api/demo'
import { getUserId } from '@/utils'
import ModelQuery from './model-query.vue'
import BenchmarkReport from './benchmark-report.vue'
import AnalysisReport from './analysis-report.vue'

export default {
  name: 'CheckData',
  components: {
    ModelQuery,
    BenchmarkReport,
    AnalysisReport
  },
  data() {
    return {
      activeTab: 'model-query', // 默认显示第一个tab
      favoritesValue: '',
      favoritesOptions: [], // 常用列表，从接口获取
      currentCommonConfig: null, // 当前选中的常用配置
      searchPanelValue: {
        projectName: [],
        modelName: [],
        productNumber: [],
        plate: [],
        platform: [],
        series: [],
        emission: [],
        burnType: [],
        engineCapacityMin: '',
        engineCapacityMax: ''
      },
      // 头部筛选项下拉选项（首次查询全部机型后生成）
      filterOptionsLoaded: false,
      filterOptions: {
        modelName: [],
        productNumber: [],
        projectName: [],
        plate: [],
        platform: [],
        series: [],
        emission: [],
        burnType: []
      },
      // 过滤后的选项数组（用于显示）
      filteredOptions: {
        modelName: [],
        productNumber: [],
        projectName: [],
        plate: [],
        platform: [],
        series: [],
        emission: [],
        burnType: []
      },
      // X轴选项（来自搜索区域的筛选项）
      xAxisOptions: [
        { label: '产品型号', value: 'modelName' },
        { label: '状态代号', value: 'productNumber' },
        { label: '项目名称', value: 'projectName' },
        { label: '板块', value: 'plate' },
        { label: '平台', value: 'platform' },
        { label: '系列', value: 'series' },
        { label: '排放', value: 'emission' },
        { label: '燃烧类型', value: 'burnType' },
        { label: '排量', value: 'engineCapacity' }
      ],
      // Y轴参数选项（通过接口获取，目前使用假数据）
      yAxisParamOptions: [],
      filteredYAxisParamOptions: [], // 过滤后的Y轴参数选项
      yAxisParamsLoaded: false, // 标记Y轴参数是否已加载
      // 机型列表（包含id和名称）
      modelList: [], // 格式: [{ id: 'xxx', name: 'xxx' }]
      // 全局选中的机型（所有图表共享）
      selectedModels: [], // 格式: [{ id: 'xxx', name: 'xxx', parameterVersion: 1 }]
      // 查询结果数据
      chartDataList: [], // 保存查询返回的 pojos 数据
      chartList: [],
      chartIdCounter: 0,
      floatingPanelExpanded: false, // 悬浮框展开状态
      formulaDialogVisible: false,
      currentFormulaChartIndex: -1,
      currentFormulaId: null, // 当前编辑的公式ID（如果为null则是新增）
      formulaFormData: {
        name: '',
        selectedParams: [], // 选中的参数列表（最多5个）
        availableParams: [], // 可用的参数列表（从selectedParams生成）
        formulaItems: [], // 公式项列表，格式: [{ type: 'param'|'operator'|'bracket'|'number', value: 'xxx', label: 'xxx' }]
        inputNumber: null, // 输入的数字
        recentNumbers: [] // 最近添加的数字列表（最多显示5个）
      },
      isDraggingOver: false, // 是否正在拖拽到预览区域
      draggingPreviewIndex: -1, // 正在拖拽的预览项索引
      dragOverPreviewIndex: -1, // 拖拽悬停的预览项索引
      formulaOperators: [
        { label: '+', value: '+' },
        { label: '-', value: '-' },
        { label: '×', value: '*' },
        { label: '÷', value: '/' }
      ],
      isResizing: false,
      resizingChartIndex: -1,
      resizeStartY: 0,
      resizeStartHeight: 0,
      // 已保存的公式列表
      savedFormulas: [], // 格式: [{ id: 'formula1', name: '公式1', formulaItems: [...] }]
      formulaIdCounter: 0, // 公式ID计数器
      operatorOptions: [
        { label: '+', value: '+' },
        { label: '-', value: '-' },
        { label: '*', value: '*' },
        { label: '/', value: '/' }
      ],
      // 添加机型弹窗相关
      addModelDialogVisible: false,
      currentChartIndex: -1, // 当前打开弹窗的图表索引
      modelListForDialog: [], // 弹窗中的机型列表
      transferData: [], // 穿梭框数据源
      transferSelectedKeys: [], // 穿梭框已选中的key数组
      loadingModelDetail: false, // 加载机型详情中
      currentEditingField: null, // 当前正在编辑的筛选字段
      openedFilterFields: new Set(), // 记录所有曾经打开过的筛选字段，这些字段不受级联筛选影响
      // 新增常用弹窗相关
      addFavoriteDialogVisible: false,
      addFavoriteFormData: {
        commonName: ''
      },
      addFavoriteFormRules: {
        commonName: [
          { required: true, message: '请输入常用名称', trigger: 'blur' },
          { max: 50, message: '常用名称不能超过50个字符', trigger: 'blur' }
        ]
      },
      savingFavorite: false // 保存常用中
    }
  },
  computed: {
    // 验证公式是否有效
    isFormulaValid() {
      return !!(
        this.formulaFormData.name &&
        this.formulaFormData.name.trim() &&
        this.formulaFormData.formulaItems &&
        this.formulaFormData.formulaItems.length > 0 &&
        this.isFormulaItemsValid()
      )
    }
  },
  watch: {
    activeTab: {
      immediate: true,
      handler(newVal, oldVal) {
        if (newVal === 'statistics') {
          window.addEventListener('resize', this.handleResize)
          // 首次进入页面时，调用查询机型接口
          if (!this.filterOptionsLoaded) {
            this.loadModelListOnFirstEnter()
          }
          // 加载Y轴参数选项
          this.loadYAxisParams()
          // 加载常用列表
          this.loadFavoritesList()
          this.$nextTick(() => {
            this.$nextTick(() => {
              // 延迟一点，确保 DOM 完全渲染
              setTimeout(() => {
                this.chartList.forEach((chart, index) => {
                  if (!chart.chartInstance) {
                    // 如果有待初始化标记，清除它
                    if (chart._pendingInit) {
                      delete chart._pendingInit
                      delete chart._pendingInitIndex
                    }
                    this.initChart(index)
                  } else {
                    chart.chartInstance.resize()
                  }
                })
              }, 100)
            })
          })
        } else if (oldVal === 'statistics') {
          window.removeEventListener('resize', this.handleResize)
          this.cleanupResizeListeners()
          this.disposeAllCharts()
        }
      }
    }
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize)
    this.cleanupResizeListeners()
    this.disposeAllCharts()
  },
  mounted() {
    // this.handleSearch()
  },
  methods: {
    // 穿梭框过滤方法
    filterTransferMethod(query, item) {
      // 确保 query 是字符串类型
      if (!query || typeof query !== 'string') {
        return true
      }

      // 确保 item 存在
      if (!item || typeof item !== 'object') {
        return false
      }

      const searchText = query.toLowerCase()

      // 安全地获取各项属性并转换为字符串
      const modelName = (item.modelName || '').toString().toLowerCase()
      const productNumber = (item.productNumber || '').toString().toLowerCase()
      const platform = (item.platform || '').toString().toLowerCase()
      const series = (item.series || '').toString().toLowerCase()
      const label = (item.label || '').toString().toLowerCase()

      // 如果搜索文本为空，返回 true（显示所有项）
      if (!searchText) {
        return true
      }

      // 检查是否匹配
      return (
        modelName.includes(searchText) ||
        productNumber.includes(searchText) ||
        platform.includes(searchText) ||
        series.includes(searchText) ||
        label.includes(searchText)
      )
    },
    // 加载Y轴参数选项（首次进入页面时调用）
    loadYAxisParams() {
      // 如果已经加载过，不再重复调用
      // if (this.yAxisParamsLoaded) {
      //   return
      // }

      const request = {
        ...api.GET_CHECK_DATA_Y_DATA,
        params: {},
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          console.log('Y轴参数数据:', resp)
          if (resp && resp.data) {
            // 处理返回的数据，支持多种数据格式
            if (Array.isArray(resp.data)) {
              this.yAxisParamOptions = resp.data.map((item) => ({
                label: item.name || item.label || item.parameterName || item,
                value: item.value || item.id || item.parameterName || item
              }))
            } else if (resp.data && Array.isArray(resp.data)) {
              // 如果返回的是对象，包含 paramList 数组
              this.yAxisParamOptions = resp.data.map((paramName) => ({
                label: paramName,
                value: paramName
              }))
            } else {
              this.yAxisParamOptions = []
            }
            // 初始化过滤后的选项为所有选项
            this.filteredYAxisParamOptions = this.yAxisParamOptions
            // 标记为已加载
            this.yAxisParamsLoaded = true
          } else {
            this.yAxisParamOptions = []
            this.filteredYAxisParamOptions = []
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取Y轴参数失败:', err)
          this.yAxisParamOptions = []
        })
    },
    handleTabClick(tab) {
      // Tab切换时的处理逻辑
      console.log('切换到tab:', tab.name)
      if (tab.name === 'statistics') {
        // 首次进入statistics tab时，加载Y轴参数选项
        this.loadYAxisParams()
        // this.handleSearch()
      }
    },
    handleAddChart() {
      const newChart = {
        id: this.chartIdCounter++,
        title: '自定义标题',
        isEditingTitle: false,
        chartType: 'line',
        xAxis:  '',
        yAxisParam:  [],
        yAxisFormula: '',
        yAxisMin: 0,
        yAxisMax: 100,
        chartHeight: 400,
        customPointX: null,
        customPointY: null,
        scatterTrendline: false,
        chartInstance: null,
        formulaItems: [],
        selectedModels: [...this.selectedModels], // 使用全局选中的机型（查询结果就是所有图表的机型），格式: [{ id: 'xxx', name: 'xxx', parameterVersion: 1 }]
        chartDataList: [], // 当前图表的数据列表（根据选择状态过滤后的数据）
        cachedModelData: {}, // 已查询的机型数据缓存，格式: { modelId: [数据数组] }
        newSelectedModels: [] // 新选择的机型，用于标记需要查询的机型
      }
      // 新增的图表展示在第一个
      // 确保响应式更新：先创建新数组，再赋值（特别是在执行过查询后可能影响响应式）
      const newChartList = [newChart, ...this.chartList]
      this.chartList = newChartList
      // 强制更新视图，确保 DOM 完全更新（特别是在执行过查询后）
      this.$forceUpdate()
      // 使用多重 nextTick 和 requestAnimationFrame 确保 DOM 完全渲染（特别是从空列表添加第一个图表时）
      this.$nextTick(() => {
        this.$nextTick(() => {
          // 使用 requestAnimationFrame 确保在下一帧渲染后再初始化
          requestAnimationFrame(() => {
            requestAnimationFrame(() => {
              // 再延迟一点，确保容器已经渲染并有尺寸
              setTimeout(() => {
                // 优先初始化新加的图表
                this.initChart(0)
                // 如果存在其他未初始化的图表，补充初始化一次，避免索引变动导致未挂载
                this.chartList.forEach((chart, idx) => {
                  if (idx !== 0 && chart && !chart.chartInstance) {
                    this.initChart(idx)
                  }
                })
                // 如果有全局选中的机型，从其他图表的缓存中复制数据到新图表
                if (this.selectedModels && this.selectedModels.length > 0 && this.chartList.length > 0) {
                  const newChart = this.chartList[0]
                  // 从第一个已有缓存的图表中复制缓存数据（所有图表共享相同数据）
                  const sourceChart = this.chartList.find((c) => c.cachedModelData && Object.keys(c.cachedModelData).length > 0)
                  if (sourceChart && sourceChart.cachedModelData) {
                    newChart.cachedModelData = JSON.parse(JSON.stringify(sourceChart.cachedModelData))
                    // 更新新图表的数据
                    this.updateChartDataFromCache(0)
                    this.updateChart(0)
                  }
                }
              }, 300) // 增加延迟时间，确保 DOM 完全渲染
            })
          })
        })
      })
    },
    toggleFloatingPanel() {
      this.floatingPanelExpanded = !this.floatingPanelExpanded
    },
    scrollToTop() {
      // 找到统计tab的容器并滚动到顶部
      const statisticsTab = document.querySelector('.statistics-tab')
      if (statisticsTab) {
        statisticsTab.scrollTo({
          top: 0,
          behavior: 'smooth'
        })
      } else {
        // 如果没有找到，则滚动整个页面
        window.scrollTo({
          top: 0,
          behavior: 'smooth'
        })
      }
    },
    handleDownloadChart(index) {
      const chart = this.chartList[index]
      if (!chart || !chart.chartInstance) {
        this.$message.warning('图表未初始化，无法导出')
        return
      }

      try {
        // 使用 getDataURL 导出图片
        const url = chart.chartInstance.getDataURL({
          type: 'png',
          pixelRatio: 2, // 提高图片清晰度
          backgroundColor: '#fff'
        })

        // 创建下载链接
        const link = document.createElement('a')
        link.href = url
        link.download = `${chart.title || 'chart'}_${new Date().getTime()}.png`
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)

        this.$message.success('图表导出成功')
      } catch (error) {
        console.error('导出图表失败:', error)
        this.$message.error('导出图表失败，请重试')
      }
    },
    handleDeleteChart(index) {
      const chart = this.chartList[index]
      if (!chart) return

      // 先清理图表实例
      if (chart.chartInstance) {
        try {
          chart.chartInstance.dispose()
        } catch (e) {
          console.warn('销毁图表实例时出错:', e)
        }
        chart.chartInstance = null
      }

      // 清理图表相关的数据
      chart.selectedModels = []
      chart.chartDataList = []
      chart.cachedModelData = {}
      chart.newSelectedModels = []

      // 删除图表
      this.chartList.splice(index, 1)

      // 删除后强制更新视图，确保所有组件都被正确清理
      // 特别是删除最后一个图表后，需要确保视图完全更新
      this.$forceUpdate()
      this.$nextTick(() => {
        this.$forceUpdate()

        // 删除后重新检查剩余图表的初始化状态
        // 使用双重 nextTick 确保 DOM 完全更新
        this.$nextTick(() => {
          this.chartList.forEach((c, idx) => {
            if (c && !c.chartInstance) {
              // 确保容器引用正确
              const refName = `chartContainer-${idx}`
              const containerRef = this.$refs[refName]
              if (containerRef) {
                this.initChart(idx)
              }
            }
          })
        })
      })
    },
    handleClearAllCharts() {
      this.disposeAllCharts()
      // 清空列表 - 使用 splice 确保响应式更新
      this.chartList.splice(0, this.chartList.length)
      this.floatingPanelExpanded = false // 清空后重置悬浮框状态
      // 强制更新视图，确保所有组件都被正确清理
      this.$nextTick(() => {
        this.$forceUpdate()
        // 再次确保视图更新
        this.$nextTick(() => {
          this.$forceUpdate()
        })
      })
    },
    // 头部筛选下拉框的过滤方法 - 产品型号
    filterModelNameOptions(query) {
      if (!query || query.trim() === '') {
        // 如果查询为空，显示级联筛选后的选项（如果已更新），否则显示所有选项
        if (this.filteredOptions.modelName && this.filteredOptions.modelName.length > 0) {
          return
        }
        this.filteredOptions.modelName = this.filterOptions.modelName || []
        return
      }
      // 将查询字符串转为小写进行不区分大小写的模糊匹配
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.modelName.length > 0
        ? this.filteredOptions.modelName
        : (this.filterOptions.modelName || [])
      this.filteredOptions.modelName = baseOptions.filter((option) => {
        // 在 label 中查找是否包含查询字符串
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 状态代号
    filterProductNumberOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.productNumber && this.filteredOptions.productNumber.length > 0) {
          return
        }
        this.filteredOptions.productNumber = this.filterOptions.productNumber || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.productNumber.length > 0
        ? this.filteredOptions.productNumber
        : (this.filterOptions.productNumber || [])
      this.filteredOptions.productNumber = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 项目名称
    filterProjectNameOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.projectName && this.filteredOptions.projectName.length > 0) {
          return
        }
        this.filteredOptions.projectName = this.filterOptions.projectName || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.projectName.length > 0
        ? this.filteredOptions.projectName
        : (this.filterOptions.projectName || [])
      this.filteredOptions.projectName = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 板块
    filterPlateOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.plate && this.filteredOptions.plate.length > 0) {
          return
        }
        this.filteredOptions.plate = this.filterOptions.plate || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.plate.length > 0
        ? this.filteredOptions.plate
        : (this.filterOptions.plate || [])
      this.filteredOptions.plate = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 平台
    filterPlatformOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.platform && this.filteredOptions.platform.length > 0) {
          return
        }
        this.filteredOptions.platform = this.filterOptions.platform || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.platform.length > 0
        ? this.filteredOptions.platform
        : (this.filterOptions.platform || [])
      this.filteredOptions.platform = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 系列
    filterSeriesOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.series && this.filteredOptions.series.length > 0) {
          return
        }
        this.filteredOptions.series = this.filterOptions.series || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.series.length > 0
        ? this.filteredOptions.series
        : (this.filterOptions.series || [])
      this.filteredOptions.series = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 燃烧类型
    filterBurnTypeOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.burnType && this.filteredOptions.burnType.length > 0) {
          return
        }
        this.filteredOptions.burnType = this.filterOptions.burnType || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.burnType.length > 0
        ? this.filteredOptions.burnType
        : (this.filterOptions.burnType || [])
      this.filteredOptions.burnType = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 头部筛选下拉框的过滤方法 - 排放
    filterEmissionOptions(query) {
      if (!query || query.trim() === '') {
        if (this.filteredOptions.emission && this.filteredOptions.emission.length > 0) {
          return
        }
        this.filteredOptions.emission = this.filterOptions.emission || []
        return
      }
      const queryLower = query.toLowerCase().trim()
      const baseOptions = this.filteredOptions.emission.length > 0
        ? this.filteredOptions.emission
        : (this.filterOptions.emission || [])
      this.filteredOptions.emission = baseOptions.filter((option) => {
        return option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // Y轴参数选择下拉框的过滤方法
    handleFilterYAxisParam(query) {
      // 确保 query 是字符串类型
      if (!query || typeof query !== 'string' || query.trim() === '') {
        // 如果查询为空，显示所有选项
        this.filteredYAxisParamOptions = this.yAxisParamOptions || []
        return
      }
      // 将查询字符串转为小写进行不区分大小写的模糊匹配
      const queryLower = query.toLowerCase().trim()
      const options = this.yAxisParamOptions || []
      this.filteredYAxisParamOptions = options.filter((option) => {
        // 在 label 中查找是否包含查询字符串
        return option && option.label && option.label.toLowerCase().includes(queryLower)
      })
    },
    // 首次进入页面时加载机型列表
    loadModelListOnFirstEnter() {
      const request = {
        ...api.GET_CHECK_LIST,
        params: {},
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          console.log('首次加载机型列表:', resp)
          if (resp && resp.data) {
            const newModelList = Array.isArray(resp.data) ? resp.data : []
            // 根据结果构建筛选下拉选项
            this.buildFilterOptions(newModelList)
            this.filterOptionsLoaded = true
            this.modelList = newModelList
            // 更新级联筛选选项
            this.updateCascadingFilterOptions()
          }
        })
        .asyncErrorCatch((err) => {
          console.error('首次加载机型列表失败:', err)
        })
    },
    // 根据机型列表构建头部筛选下拉选项（仅首次调用）
    buildFilterOptions(modelList) {
      if (!Array.isArray(modelList) || modelList.length === 0) {
        return
      }

      const fields = [
        { key: 'modelName', target: 'modelName' },
        { key: 'productNumber', target: 'productNumber' },
        { key: 'projectName', target: 'projectName' },
        { key: 'plate', target: 'plate' },
        { key: 'platform', target: 'platform' },
        { key: 'series', target: 'series' },
        { key: 'emission', target: 'emission' },
        { key: 'burnType', target: 'burnType' }
      ]

      const valueSets = {}
      fields.forEach(({ target }) => {
        valueSets[target] = new Set()
      })

      modelList.forEach((item) => {
        if (!item || typeof item !== 'object') return
        fields.forEach(({ key, target }) => {
          const val = item[key]
          if (val !== undefined && val !== null && val !== '') {
            valueSets[target].add(String(val))
          }
        })
      })

      const newFilterOptions = {}
      const newFilteredOptions = {}
      Object.keys(this.filterOptions).forEach((fieldKey) => {
        const values = Array.from(valueSets[fieldKey] || [])
        // 简单排序，中文会按编码排序
        values.sort()
        const options = values.map((v) => ({
          label: v,
          value: v
        }))
        newFilterOptions[fieldKey] = options
        // 初始化过滤后的选项为所有选项
        newFilteredOptions[fieldKey] = options
      })

      this.filterOptions = newFilterOptions
      this.filteredOptions = newFilteredOptions
    },
    // 加载常用列表
    loadFavoritesList() {
      const request = {
        ...api.GET_CHART_COMMONLY_USED,
        params: {
          userId: getUserId()
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          if (resp && resp.data) {
            // 处理返回的数据，转换为下拉选项格式
            let favoritesList = []
            if (Array.isArray(resp.data)) {
              favoritesList = resp.data
            } else if (resp.data.list && Array.isArray(resp.data.list)) {
              favoritesList = resp.data.list
            } else if (resp.data.data && Array.isArray(resp.data.data)) {
              favoritesList = resp.data.data
            }

            this.favoritesOptions = favoritesList.map((item) => ({
              label: item.commonName || item.name || '',
              value: item.commonId || item.id || '',
              data: item // 保存完整数据，用于后续使用
            }))
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取常用列表失败:', err)
          this.$message.error('获取常用列表失败')
        })
    },
    // 常用选择变化
    handleFavoriteChange(value) {
      if (!value) {
        // 清空常用配置
        this.currentCommonConfig = null
        return
      }

      // 查找选中的常用配置
      const selectedFavorite = this.favoritesOptions.find((item) => {
        return (
          item.value === value ||
          (item.data && (item.data.commonId === value || item.data.id === value || item.data.commonName === value))
        )
      })
      if (!selectedFavorite || !selectedFavorite.data) {
        this.$message({
          type: 'warning',
          message: '未找到选中的常用配置'
        })
        return
      }

      // 保存常用配置
      this.currentCommonConfig = selectedFavorite.data

      // 根据常用配置生成图表
      this.generateChartFromFavorite(selectedFavorite.data)
    },
    // 根据常用配置生成图表
    generateChartFromFavorite(favoriteConfig) {
      if (!favoriteConfig) {
        return
      }

      // 常用配置的格式可能有两种：
      // 1. 包含 charts 数组的格式
      // 2. 直接是图表配置对象的格式（兼容后端返回的格式）
      let charts = []
      
      // 如果存在 charts 数组，使用它
      if (favoriteConfig.charts && Array.isArray(favoriteConfig.charts)) {
        charts = favoriteConfig.charts
      } 
      // 如果直接是图表配置对象（兼容后端返回格式：xaxis, yaxis 等字段）
      else if (favoriteConfig.xaxis || favoriteConfig.xAxis || favoriteConfig.chartType) {
        charts = [favoriteConfig]
      }
      // 如果都不存在，尝试从其他可能的字段获取
      else if (favoriteConfig.id || favoriteConfig.rowId) {
        charts = [favoriteConfig]
      }

      if (!Array.isArray(charts) || charts.length === 0) {
        this.$message.warning('该常用配置中没有图表数据')
        return
      }

      // 先清空现有图表
      this.disposeAllCharts()
      this.chartList = []

      // 为每个图表配置创建图表
      const newCharts = charts.map((chartConfig) => {
        // 兼容多种字段名：xaxis (小写) 或 xAxis (驼峰)
        const xAxisValue = chartConfig.xaxis || chartConfig.xAxis || ''
        
        // 匹配 xAxis：确保 xAxis 值在 xAxisOptions 中存在
        console.log('xAxisValue', xAxisValue)
        let matchedXAxis = ''
        if (xAxisValue) {
          const xAxisOption = this.xAxisOptions.find((opt) => opt.value === xAxisValue)
          if (xAxisOption) {
            matchedXAxis = xAxisValue
          } else {
            // 如果找不到匹配的 xAxis，使用默认值
            matchedXAxis = this.xAxisOptions.length > 0 ? this.xAxisOptions[0].value : ''
          }
        } else {
          matchedXAxis = this.xAxisOptions.length > 0 ? this.xAxisOptions[0].value : ''
        }

        // 从 yAxis 字段读取y轴选中的内容，兼容多种格式：
        // 1. yaxis (小写) 或 yAxis (驼峰)
        // 2. 可能是字符串格式的 JSON，如 "[]" 或 '["param1", "param2"]'
        // 3. 可能是数组格式
        let yAxisArray = []
        const yAxisValue = chartConfig.yaxis || chartConfig.yAxis || chartConfig.yaxisParameters
        
        if (yAxisValue) {
          if (Array.isArray(yAxisValue)) {
            // 已经是数组格式
            yAxisArray = yAxisValue
          } else if (typeof yAxisValue === 'string') {
            // 字符串格式，尝试解析 JSON
            try {
              const parsed = JSON.parse(yAxisValue)
              if (Array.isArray(parsed)) {
                yAxisArray = parsed
              } else if (parsed) {
                // 如果不是数组，转为数组
                yAxisArray = [parsed]
              }
            } catch (e) {
              // 解析失败，当作单个值处理
              if (yAxisValue.trim() !== '' && yAxisValue !== '[]') {
                yAxisArray = [yAxisValue]
              }
            }
          } else {
            // 其他类型，转为数组
            yAxisArray = [yAxisValue]
          }
        }

        // 匹配 yAxis：确保 yAxis 中的每个值都在 yAxisParamOptions 中存在
        const yAxisParam = yAxisArray.filter((yAxisValue) => {
          // 在 yAxisParamOptions 中查找匹配的值
          return this.yAxisParamOptions.some((opt) => opt.value === yAxisValue)
        })

        return {
          id: this.chartIdCounter++,
          title: chartConfig.title || '自定义标题',
          isEditingTitle: false,
          chartType: chartConfig.chartType || 'line',
          xAxis: matchedXAxis, // 匹配后的 xAxis
          yAxisParam: yAxisParam, // 匹配后的 yAxisParam（从yAxis字段读取并匹配）
          yAxisFormula: chartConfig.yAxisFormula || '',
          yAxisMin: chartConfig.yAxisMin !== undefined ? chartConfig.yAxisMin : 0,
          yAxisMax: chartConfig.yAxisMax !== undefined ? chartConfig.yAxisMax : 100,
          chartHeight: 400,
          customPointX: chartConfig.customPointX || null,
          customPointY: chartConfig.customPointY || null,
          scatterTrendline: chartConfig.scatterTrendline || false,
          chartInstance: null,
          formulaItems: chartConfig.formulaItems || [],
          selectedModels: [...this.selectedModels], // 使用全局选中的机型
          chartDataList: [], // 当前图表的数据列表
          cachedModelData: {}, // 已查询的机型数据缓存
          newSelectedModels: [] // 新选择的机型
        }
      })

      // 将所有新图表添加到列表
      this.chartList = newCharts
      this.$forceUpdate()

      // 使用多重 nextTick 确保 DOM 完全渲染
      this.$nextTick(() => {
        this.$nextTick(() => {
          requestAnimationFrame(() => {
            requestAnimationFrame(() => {
              setTimeout(() => {
                // 初始化所有图表
                this.chartList.forEach((chart, idx) => {
                  if (!chart.chartInstance) {
                    this.initChart(idx)
                  }
                })
                // 如果有全局选中的机型，从其他图表的缓存中复制数据到新图表
                if (this.selectedModels && this.selectedModels.length > 0 && this.chartList.length > 0) {
                  const sourceChart = this.chartList.find((c) => c.cachedModelData && Object.keys(c.cachedModelData).length > 0)
                  if (sourceChart && sourceChart.cachedModelData) {
                    this.chartList.forEach((chart, idx) => {
                      chart.cachedModelData = JSON.parse(JSON.stringify(sourceChart.cachedModelData))
                      // 更新图表的数据
                      this.updateChartDataFromCache(idx)
                      this.updateChart(idx)
                    })
                  }
                }
              }, 300)
            })
          })
        })
      })
    },
    // 打开新增常用弹窗
    handleAddFavorite() {
      // 检查是否有图表
      if (!this.chartList || this.chartList.length === 0) {
        this.$message({
          type: 'warning',
          message: '当前没有图表，请先创建图表'
        })
        return
      }
      // 打开新增常用弹窗
      this.addFavoriteDialogVisible = true
    },
    // 关闭新增常用弹窗
    handleAddFavoriteDialogClose() {
      this.addFavoriteDialogVisible = false
      this.addFavoriteFormData.commonName = ''
      // 清空表单验证
      if (this.$refs.addFavoriteForm) {
        this.$refs.addFavoriteForm.clearValidate()
      }
    },
    // 确认新增常用
    handleConfirmAddFavorite() {
      // 表单验证
      this.$refs.addFavoriteForm.validate((valid) => {
        if (!valid) {
          return false
        }

        // 检查是否有图表
        if (!this.chartList || this.chartList.length === 0) {
          this.$message({
            type: 'warning',
            message: '当前没有图表，请先创建图表'
          })
          return
        }

        // 收集当前所有图表的配置
        const charts = this.collectCurrentChartsConfig()

        if (!charts || charts.length === 0) {
          this.$message({
            type: 'warning',
            message: '当前没有可保存的图表配置'
          })
          return
        }

        // 构建保存数据
        const requestData = {
          userId: getUserId(),
          commonName: this.addFavoriteFormData.commonName,
          charts: charts
        }

        // 调用保存接口
        this.savingFavorite = true
        const request = {
          ...api.ADD_CHART_COMMONLY_USED,
          params: requestData,
          disableSuccessMsg: true
        }

        this.$request(request)
          .asyncThen((resp) => {
            this.$message({
              message: '新增常用成功',
              type: 'success'
            })
            this.handleAddFavoriteDialogClose()
            // 重新加载常用列表
            this.loadFavoritesList()
          })
          .asyncErrorCatch((err) => {
            console.error('新增常用失败:', err)
            this.$message({
              message: err.message || '新增常用失败',
              type: 'error'
            })
          })
          .finally(() => {
            this.savingFavorite = false
          })
      })
    },
    // 更新常用
    handleUpdateFavorite() {
      // 检查是否有已选择的"我的常用"
      if (!this.currentCommonConfig) {
        this.$message({
          type: 'warning',
          message: '请先选择一个常用配置'
        })
        return
      }

      // 检查是否有图表
      if (!this.chartList || this.chartList.length === 0) {
        this.$message({
          type: 'warning',
          message: '当前没有图表，请先创建图表'
        })
        return
      }

      // 收集当前所有图表的配置
      const charts = this.collectCurrentChartsConfig()

      if (!charts || charts.length === 0) {
        this.$message({
          type: 'warning',
          message: '当前没有可保存的图表配置'
        })
        return
      }

      // 构建更新数据
      const requestData = {
        userId: getUserId(),
        commonName: this.currentCommonConfig.commonName || this.currentCommonConfig.name,
        commonId: this.currentCommonConfig.commonId || this.currentCommonConfig.id,
        charts: charts
      }

      // 调用更新接口
      this.savingFavorite = true
      const request = {
        ...api.EDIT_CHART_COMMONLY_USED,
        params: requestData,
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          this.$message({
            message: '更新常用成功',
            type: 'success'
          })
          // 重新加载常用列表
          this.loadFavoritesList()
        })
        .asyncErrorCatch((err) => {
          console.error('更新常用失败:', err)
          this.$message({
            message: err.message || '更新常用失败',
            type: 'error'
          })
        })
        .finally(() => {
          this.savingFavorite = false
        })
    },
    // 收集当前所有图表的配置
    collectCurrentChartsConfig() {
      if (!this.chartList || this.chartList.length === 0) {
        return []
      }

      return this.chartList.map((chart) => {
        // 确保 yAxis 是数组格式
        let yAxis = []
        if (chart.yAxisParam) {
          if (Array.isArray(chart.yAxisParam)) {
            yAxis = chart.yAxisParam
          } else {
            yAxis = [chart.yAxisParam]
          }
        }

        // 只保留这四个字段
        return {
          title: chart.title || '自定义标题',
          chartType: chart.chartType || 'line',
          xAxis: chart.xAxis || '',
          yAxis: yAxis // y轴选中的内容放在yAxis中
        }
      })
    },
    handleSearch() {
      // 如果机型列表为空，先获取机型列表
      if (!this.modelList || this.modelList.length === 0) {
        // 先获取机型列表
        const params = {}
        const arrayFields = ['modelName', 'productNumber', 'projectName', 'plate', 'platform', 'series', 'emission', 'burnType']
        arrayFields.forEach((field) => {
          const value = this.searchPanelValue[field]
          if (Array.isArray(value) && value.length > 0) {
            params[field] = value
          }
        })
        // 排量范围
        if (this.searchPanelValue.engineCapacityMin) {
          params.engineCapacityMin = this.searchPanelValue.engineCapacityMin
        }
        if (this.searchPanelValue.engineCapacityMax) {
          params.engineCapacityMax = this.searchPanelValue.engineCapacityMax
        }

        const listRequest = {
          ...api.GET_CHECK_LIST,
          params: params,
          disableSuccessMsg: true
        }

        this.$request(listRequest)
          .asyncThen((resp) => {
            if (resp && resp.data) {
              const newModelList = Array.isArray(resp.data) ? resp.data : []
              // 如果是首次查询（加载全部机型），根据结果构建筛选下拉选项
              if (!this.filterOptionsLoaded) {
                this.buildFilterOptions(newModelList)
                this.filterOptionsLoaded = true
              }
              this.modelList = newModelList
              // 更新级联筛选选项
              this.updateCascadingFilterOptions()
              // 根据筛选条件确定选中的机型
              this.updateSelectedModelsFromFilters()
              // 继续执行查询参数的逻辑
              this.queryParamsBySelectedModels()
            }
          })
          .asyncErrorCatch((err) => {
            console.error('获取机型列表失败:', err)
            this.$message.error('获取机型列表失败，请重试')
          })
        return
      }

      // 如果机型列表已存在，直接根据筛选条件确定选中的机型并查询参数
      this.updateCascadingFilterOptions()
      this.updateSelectedModelsFromFilters()
      this.queryParamsBySelectedModels()
    },
    // 根据选中的机型查询参数
    queryParamsBySelectedModels() {
      // 如果没有选中的机型，提示用户
      if (!this.selectedModels || this.selectedModels.length === 0) {
        this.$message.warning('该筛选条件下没有匹配的机型')
        return
      }

      // 显示全屏 loading
      const loadingInstance = this.$loading({
        lock: true,
        text: '正在查询参数。。',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })

      // 获取所有选中的机型ID
      const modelIds = this.selectedModels.map((m) => m.id)
      const request = {
        ...api.GET_CHECK_DATA_CHARTS,
        params: modelIds, // 传机型id数组
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          console.log('查询参数返回:', resp)
          // 处理返回的数据
          if (resp && resp.data) {
            // 更新Y轴参数选项（支持多种数据格式）
            let newParamOptions = []
            if (resp.data.paramList && Array.isArray(resp.data.paramList)) {
              // 如果返回的是对象，包含 paramList 数组
              newParamOptions = resp.data.paramList.map((paramName) => ({
                label: paramName,
                value: paramName
              }))
            } else if (Array.isArray(resp.data)) {
              // 如果返回的是数组
              newParamOptions = resp.data.map((item) => ({
                label: item.name || item.label || item.parameterName || item,
                value: item.value || item.id || item.parameterName || item
              }))
            }

            // 合并新的参数选项到现有选项中（避免重复）
            if (newParamOptions.length > 0) {
              const existingParamMap = new Map()
              this.yAxisParamOptions.forEach((opt) => {
                existingParamMap.set(opt.value, opt)
              })
              newParamOptions.forEach((opt) => {
                if (!existingParamMap.has(opt.value)) {
                  existingParamMap.set(opt.value, opt)
                }
              })
              this.yAxisParamOptions = Array.from(existingParamMap.values())
              // 更新过滤后的选项为所有选项
              this.filteredYAxisParamOptions = this.yAxisParamOptions
            }

            // 处理返回的数据，按机型ID分组保存到所有图表的缓存
            const pojosData = resp.data.pojos || []
            console.log('查询返回的数据:', pojosData)
            console.log('选中的机型:', this.selectedModels)

            if (pojosData.length > 0) {
              // 遍历所有图表，更新缓存数据
              this.chartList.forEach((chart) => {
                // 初始化缓存对象
                if (!chart.cachedModelData) {
                  chart.cachedModelData = {}
                }

                // 查询返回的pojosData是一个数组，每个元素代表一个机型的数据
                pojosData.forEach((modelData) => {
                  // 尝试多种方式获取机型ID
                  let modelId = modelData.id || modelData.modelId || modelData.engineModelID || modelData.rowId

                  // 如果无法从数据中获取ID，尝试通过机型名称匹配
                  if (!modelId) {
                    const modelName = modelData.modelName || modelData.productFullName || ''
                    const matchedModel = this.selectedModels.find((m) => {
                      return m.name === modelName || String(m.id) === String(modelData.id)
                    })
                    if (matchedModel) {
                      modelId = matchedModel.id
                    }
                  }

                  // 如果找到了机型ID，保存到缓存
                  if (modelId) {
                    const modelIdStr = String(modelId)
                    // 如果该机型已有缓存数据，合并数据（避免重复）
                    if (chart.cachedModelData[modelIdStr]) {
                      // 检查是否已存在相同的数据，避免重复添加
                      const exists = chart.cachedModelData[modelIdStr].some((existing) => {
                        return JSON.stringify(existing) === JSON.stringify(modelData)
                      })
                      if (!exists) {
                        chart.cachedModelData[modelIdStr].push(modelData)
                      }
                    } else {
                      chart.cachedModelData[modelIdStr] = [modelData]
                    }
                  }
                })
              })
            }

            // 更新所有图表的数据和显示
            // 查询结果就是所有图表的机型，所有图表都使用这个查询结果
            this.chartList.forEach((chart, index) => {
              // 将全局选中的机型同步到图表（查询结果就是所有图表的机型）
              chart.selectedModels = [...this.selectedModels]
              // 从缓存中获取数据并更新图表
              this.updateChartDataFromCache(index)
              // 更新图表显示
              this.updateChart(index)
            })
          }
        })
        .asyncErrorCatch((err) => {
          console.error('查询参数失败:', err)
          this.$message.error('查询参数失败，请重试')
        })
        .finally(() => {
          // 确保 loading 在所有情况下都能关闭
          if (loadingInstance) {
            loadingInstance.close()
          }
        })
    },
    // 处理筛选条件改变
    handleFilterChange(changedField) {
      // 不清除 currentEditingField，让该字段继续不受级联筛选影响
      // 更新级联筛选选项
      this.updateCascadingFilterOptions()
      // 根据筛选条件确定选中的机型（但不触发查询参数接口）
      this.updateSelectedModelsFromFilters()
    },
    // 处理筛选下拉框显示/隐藏事件
    handleFilterVisibleChange(fieldName, visible) {
      if (visible) {
        // 下拉框打开时，设置当前正在编辑的字段
        this.currentEditingField = fieldName
        // 将该字段添加到已打开字段集合中，使其永远不受级联筛选影响
        this.openedFilterFields.add(fieldName)
        // 确保当前字段显示所有选项
        this.updateCascadingFilterOptions()
      }
      // 下拉框关闭时，不清除 currentEditingField 和 openedFilterFields
      // 该字段永远不受级联筛选影响
    },
    // 处理排量输入框失焦事件
    handleEngineCapacityBlur() {
      // 检查两个输入框是否都有值
      if (this.searchPanelValue.engineCapacityMin && this.searchPanelValue.engineCapacityMax) {
        // 检查是否有符合条件的机型
        if (!this.modelList || this.modelList.length === 0) {
          return
        }

        const min = parseFloat(this.searchPanelValue.engineCapacityMin)
        const max = parseFloat(this.searchPanelValue.engineCapacityMax)

        // 验证输入值
        if (isNaN(min) || isNaN(max) || min > max) {
          return
        }

        // 根据所有筛选条件筛选机型（包括排量范围）
        const filteredModels = this.modelList.filter((model) => {
          // 检查每个筛选条件
          const fields = [
            { key: 'modelName', value: this.searchPanelValue.modelName },
            { key: 'productNumber', value: this.searchPanelValue.productNumber },
            { key: 'projectName', value: this.searchPanelValue.projectName },
            { key: 'plate', value: this.searchPanelValue.plate },
            { key: 'platform', value: this.searchPanelValue.platform },
            { key: 'series', value: this.searchPanelValue.series },
            { key: 'emission', value: this.searchPanelValue.emission },
            { key: 'burnType', value: this.searchPanelValue.burnType }
          ]

          // 检查排量范围
          const capacity = parseFloat(model.engineCapacity || 0)
          if (capacity < min || capacity > max) {
            return false
          }

          // 检查所有筛选条件
          for (const field of fields) {
            const selectedValues = Array.isArray(field.value) ? field.value : []
            if (selectedValues.length > 0) {
              const modelValue = String(model[field.key] || '')
              if (!selectedValues.includes(modelValue)) {
                return false
              }
            }
          }

          return true
        })

        // 如果没有符合条件的机型，提示用户
        if (filteredModels.length === 0) {
          this.$message.warning('无机型数据')
        } else {
          // 如果有符合条件的机型，更新级联筛选选项和选中机型（但不触发查询参数接口）
          this.updateCascadingFilterOptions()
          this.updateSelectedModelsFromFilters()
        }
      }
    },
    // 更新级联筛选选项（根据已选中的筛选条件，动态计算其他筛选项的可选项）
    updateCascadingFilterOptions() {
      if (!this.modelList || this.modelList.length === 0) {
        // 如果没有机型列表，使用原始的 filterOptions
        this.filteredOptions = { ...this.filterOptions }
        return
      }

      // 根据已选中的筛选条件，筛选出符合条件的机型
      // 注意：筛选机型时使用所有已选的条件（包括已打开过的字段），这样才能正确筛选出符合条件的机型
      const filteredModels = this.modelList.filter((model) => {
        // 检查每个筛选条件（使用所有已选的条件）
        const fields = [
          { key: 'modelName', value: this.searchPanelValue.modelName },
          { key: 'productNumber', value: this.searchPanelValue.productNumber },
          { key: 'projectName', value: this.searchPanelValue.projectName },
          { key: 'plate', value: this.searchPanelValue.plate },
          { key: 'platform', value: this.searchPanelValue.platform },
          { key: 'series', value: this.searchPanelValue.series },
          { key: 'emission', value: this.searchPanelValue.emission },
          { key: 'burnType', value: this.searchPanelValue.burnType }
        ]

        // 检查排量范围
        if (this.searchPanelValue.engineCapacityMin || this.searchPanelValue.engineCapacityMax) {
          const capacity = parseFloat(model.engineCapacity || 0)
          const min = this.searchPanelValue.engineCapacityMin ? parseFloat(this.searchPanelValue.engineCapacityMin) : -Infinity
          const max = this.searchPanelValue.engineCapacityMax ? parseFloat(this.searchPanelValue.engineCapacityMax) : Infinity
          if (capacity < min || capacity > max) {
            return false
          }
        }

        // 检查所有筛选条件（使用所有已选的条件，包括已打开过的字段）
        for (const field of fields) {
          const selectedValues = Array.isArray(field.value) ? field.value : []
          if (selectedValues.length > 0) {
            const modelValue = String(model[field.key] || '')
            if (!selectedValues.includes(modelValue)) {
              return false
            }
          }
        }

        return true
      })

      // 根据筛选后的机型，重新计算每个筛选项的可选项
      const fields = [
        { key: 'modelName', target: 'modelName' },
        { key: 'productNumber', target: 'productNumber' },
        { key: 'projectName', target: 'projectName' },
        { key: 'plate', target: 'plate' },
        { key: 'platform', target: 'platform' },
        { key: 'series', target: 'series' },
        { key: 'emission', target: 'emission' },
        { key: 'burnType', target: 'burnType' }
      ]

      const valueSets = {}
      fields.forEach(({ target }) => {
        valueSets[target] = new Set()
      })

      filteredModels.forEach((item) => {
        if (!item || typeof item !== 'object') return
        fields.forEach(({ key, target }) => {
          const val = item[key]
          if (val !== undefined && val !== null && val !== '') {
            valueSets[target].add(String(val))
          }
        })
      })

      // 更新过滤后的选项
      // 所有曾经打开过的字段都始终显示所有选项，不受级联筛选影响
      // 级联筛选只用于确定最终选中的机型，不影响下拉选项
      const newFilteredOptions = {}
      Object.keys(this.filterOptions).forEach((fieldKey) => {
        // 如果字段曾经被打开过，或者当前正在编辑，则显示所有选项
        if (this.openedFilterFields.has(fieldKey) || fieldKey === this.currentEditingField) {
          newFilteredOptions[fieldKey] = this.filterOptions[fieldKey] || []
        } else {
          const values = Array.from(valueSets[fieldKey] || [])
          values.sort()
          const options = values.map((v) => ({
            label: v,
            value: v
          }))
          newFilteredOptions[fieldKey] = options
        }
      })

      // 如果某个字段没有可选项，使用原始的 filterOptions 中的选项
      Object.keys(this.filterOptions).forEach((fieldKey) => {
        // 曾经打开过的字段或当前正在编辑的字段已经使用原始选项，跳过
        if (this.openedFilterFields.has(fieldKey) || fieldKey === this.currentEditingField) {
          return
        }
        if (!newFilteredOptions[fieldKey] || newFilteredOptions[fieldKey].length === 0) {
          newFilteredOptions[fieldKey] = this.filterOptions[fieldKey] || []
        }
      })

      this.filteredOptions = newFilteredOptions
    },
    // 根据筛选条件确定选中的机型
    updateSelectedModelsFromFilters() {
      if (!this.modelList || this.modelList.length === 0) {
        this.selectedModels = []
        return
      }

      // 根据所有筛选条件筛选机型
      const filteredModels = this.modelList.filter((model) => {
        // 检查每个筛选条件
        const fields = [
          { key: 'modelName', value: this.searchPanelValue.modelName },
          { key: 'productNumber', value: this.searchPanelValue.productNumber },
          { key: 'projectName', value: this.searchPanelValue.projectName },
          { key: 'plate', value: this.searchPanelValue.plate },
          { key: 'platform', value: this.searchPanelValue.platform },
          { key: 'series', value: this.searchPanelValue.series },
          { key: 'emission', value: this.searchPanelValue.emission },
          { key: 'burnType', value: this.searchPanelValue.burnType }
        ]

        // 检查排量范围
        if (this.searchPanelValue.engineCapacityMin || this.searchPanelValue.engineCapacityMax) {
          const capacity = parseFloat(model.engineCapacity || 0)
          const min = this.searchPanelValue.engineCapacityMin ? parseFloat(this.searchPanelValue.engineCapacityMin) : -Infinity
          const max = this.searchPanelValue.engineCapacityMax ? parseFloat(this.searchPanelValue.engineCapacityMax) : Infinity
          if (capacity < min || capacity > max) {
            return false
          }
        }

        // 检查所有筛选条件
        for (const field of fields) {
          const selectedValues = Array.isArray(field.value) ? field.value : []
          if (selectedValues.length > 0) {
            const modelValue = String(model[field.key] || '')
            if (!selectedValues.includes(modelValue)) {
              return false
            }
          }
        }

        return true
      })

      // 转换为 selectedModels 格式
      this.selectedModels = filteredModels.map((model) => ({
        id: model.id || model.rowId || model.engineModelID,
        name: model.modelName || model.productFullName || '未知机型',
        parameterVersion: model.parameterVersion || 1
      }))
    },
    // 查询所有图表的机型数据
    queryChartDataForAllCharts() {
      // 如果没有选择机型，直接返回
      if (!this.selectedModels || this.selectedModels.length === 0) {
        return
      }

      // 获取所有选中的机型ID
      const modelIds = this.selectedModels.map((m) => m.id)
      const request = {
        ...api.GET_CHECK_DATA_CHARTS,
        params: modelIds, // 传机型id数组
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          console.log('查询图表数据返回:', resp)
          // 处理返回的数据
          if (resp && resp.data) {
            // 更新Y轴参数选项（支持多种数据格式）
            let newParamOptions = []
            if (resp.data.paramList && Array.isArray(resp.data.paramList)) {
              // 如果返回的是对象，包含 paramList 数组
              newParamOptions = resp.data.paramList.map((paramName) => ({
                label: paramName,
                value: paramName
              }))
            } else if (Array.isArray(resp.data)) {
              // 如果返回的是数组
              newParamOptions = resp.data.map((item) => ({
                label: item.name || item.label || item.parameterName || item,
                value: item.value || item.id || item.parameterName || item
              }))
            }

            // 合并新的参数选项到现有选项中（避免重复）
            if (newParamOptions.length > 0) {
              const existingParamMap = new Map()
              this.yAxisParamOptions.forEach((opt) => {
                existingParamMap.set(opt.value, opt)
              })
              newParamOptions.forEach((opt) => {
                if (!existingParamMap.has(opt.value)) {
                  existingParamMap.set(opt.value, opt)
                }
              })
              this.yAxisParamOptions = Array.from(existingParamMap.values())
              // 更新过滤后的选项为所有选项
              this.filteredYAxisParamOptions = this.yAxisParamOptions
            }

            // 处理返回的数据，按机型ID分组保存到所有图表的缓存
            const pojosData = resp.data.pojos || []
            console.log('查询返回的数据:', pojosData)
            console.log('选中的机型:', this.selectedModels)

            if (pojosData.length > 0) {
              // 遍历所有图表，更新缓存数据
              this.chartList.forEach((chart) => {
                // 初始化缓存对象
                if (!chart.cachedModelData) {
                  chart.cachedModelData = {}
                }

                // 查询返回的pojosData是一个数组，每个元素代表一个机型的数据
                pojosData.forEach((modelData) => {
                  // 尝试多种方式获取机型ID
                  let modelId = modelData.id || modelData.modelId || modelData.engineModelID || modelData.rowId

                  // 如果无法从数据中获取ID，尝试通过机型名称匹配
                  if (!modelId) {
                    const modelName = modelData.modelName || modelData.productFullName || ''
                    const matchedModel = this.selectedModels.find((m) => {
                      return m.name === modelName || String(m.id) === String(modelData.id)
                    })
                    if (matchedModel) {
                      modelId = matchedModel.id
                    }
                  }

                  // 如果找到了机型ID，保存到缓存
                  if (modelId) {
                    const modelIdStr = String(modelId)
                    // 如果该机型已有缓存数据，合并数据（避免重复）
                    if (chart.cachedModelData[modelIdStr]) {
                      // 检查是否已存在相同的数据，避免重复添加
                      const exists = chart.cachedModelData[modelIdStr].some((existing) => {
                        return JSON.stringify(existing) === JSON.stringify(modelData)
                      })
                      if (!exists) {
                        chart.cachedModelData[modelIdStr].push(modelData)
                      }
                    } else {
                      chart.cachedModelData[modelIdStr] = [modelData]
                    }
                  }
                })
              })
            }

            // 更新所有图表的数据和显示
            this.chartList.forEach((chart, index) => {
              // 将全局选中的机型同步到图表
              chart.selectedModels = [...this.selectedModels]
              // 从缓存中获取数据并更新图表
              this.updateChartDataFromCache(index)
              // 更新图表显示
              this.updateChart(index)
            })
          }
        })
        .asyncErrorCatch((err) => {
          console.error('查询图表数据失败:', err)
          this.$message.error('查询图表数据失败，请重试')
        })
    },
    resetSearch() {
      this.searchPanelValue = {
        projectName: [],
        modelName: [],
        productNumber: [],
        plate: [],
        platform: [],
        series: [],
        emission: [],
        burnType: [],
        engineCapacityMin: '',
        engineCapacityMax: ''
      }
      // 清空查询结果数据
      this.modelList = []
      this.selectedModels = [] // 清空全局选中的机型
      this.chartDataList = []
      this.yAxisParamOptions = []
      this.filteredYAxisParamOptions = []
      // 清空已打开字段集合
      this.openedFilterFields.clear()
      this.currentEditingField = null
      // 重置过滤后的选项为所有选项
      this.filteredOptions = {
        modelName: this.filterOptions.modelName,
        productNumber: this.filterOptions.productNumber,
        projectName: this.filterOptions.projectName,
        plate: this.filterOptions.plate,
        platform: this.filterOptions.platform,
        series: this.filterOptions.series,
        emission: this.filterOptions.emission,
        burnType: this.filterOptions.burnType
      }
      // 清空所有图表的数据和机型选择
      this.chartList.forEach((chart) => {
        chart.selectedModels = []
        chart.chartDataList = []
        chart.cachedModelData = {}
        // 更新图表显示
        this.updateChart(this.chartList.indexOf(chart))
      })
    },
    initChart(index) {
      const chart = this.chartList[index]
      if (!chart) return
      if (!chart.chartHeight) {
        chart.chartHeight = 400
      }

      const refName = `chartContainer-${index}`
      const getContainer = () => {
        // 优先使用 $refs
        const containerRef = this.$refs[refName]
        if (containerRef) {
          return Array.isArray(containerRef) ? containerRef[0] : containerRef
        }
        // 如果 $refs 获取不到，尝试使用 querySelector 作为备选方案
        const chartAreas = document.querySelectorAll('.chart-area')
        if (chartAreas && chartAreas[index]) {
          const container = chartAreas[index].querySelector('.chart-container')
          if (container) {
            return container
          }
        }
        return null
      }

      // 使用递归重试机制，确保容器存在且有尺寸
      const tryInitChart = (retryCount = 0, maxRetries = 30) => {
        const container = getContainer()

        if (!container) {
          if (retryCount >= maxRetries) {
            console.warn(`初始化图表失败，已重试 ${maxRetries} 次，无法找到容器，索引: ${index}`)
            return
          }
          // 容器不存在，延迟后重试
          setTimeout(() => {
            tryInitChart(retryCount + 1, maxRetries)
          }, 150)
          return
        }

        // 检查容器是否可见
        const style = window.getComputedStyle(container)
        const isVisible = style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'

        // 使用多种方式检查容器尺寸（更可靠）
        const rect = container.getBoundingClientRect()
        const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
                        (rect.width > 0 && rect.height > 0) ||
                        (container.clientWidth > 0 && container.clientHeight > 0)

        // 如果容器不可见，需要等待
        if (!isVisible) {
          if (retryCount >= maxRetries) {
            console.warn(`容器不可见，无法初始化图表，索引: ${index}`)
            return
          }
          setTimeout(() => {
            tryInitChart(retryCount + 1, maxRetries)
          }, 150)
          return
        }

        if (!hasSize) {
          // 检查父元素是否有尺寸
          const parent = container.parentElement
          const parentHasSize = parent && (parent.offsetWidth > 0 || parent.clientWidth > 0)

          // 如果父元素有尺寸但容器没有，可能是样式还没应用，尝试强制触发重排
          if (parentHasSize && retryCount < maxRetries - 3) {
            // 强制触发重排
            void container.offsetHeight
            // 延迟后重试
            setTimeout(() => {
              tryInitChart(retryCount + 1, maxRetries)
            }, 150)
            return
          }

          // 在最后几次重试时，使用 ResizeObserver 监听尺寸变化
          if (retryCount >= maxRetries - 5 && typeof ResizeObserver !== 'undefined' && !container._resizeObserver) {
            container._resizeObserver = new ResizeObserver((entries) => {
              for (const entry of entries) {
                const target = entry.target
                const targetRect = target.getBoundingClientRect()
                const targetHasSize = (target.offsetWidth > 0 && target.offsetHeight > 0) ||
                                      (targetRect.width > 0 && targetRect.height > 0)

                if (targetHasSize && !chart.chartInstance) {
                  // 容器有尺寸了，初始化图表
                  this.initChartWithContainer(index, target)
                  // 清理观察者
                  if (target._resizeObserver) {
                    target._resizeObserver.disconnect()
                    delete target._resizeObserver
                  }
                }
              }
            })
            container._resizeObserver.observe(container)

            // 设置超时，如果3秒后还没有尺寸，就尝试强制初始化
            setTimeout(() => {
              if (container._resizeObserver) {
                container._resizeObserver.disconnect()
                delete container._resizeObserver
              }
              if (!chart.chartInstance) {
                // 最后尝试：即使没有尺寸也初始化，并监听 resize 事件
                this.initChartWithResizeObserver(index, container, chart)
              }
            }, 3000)
          }

          if (retryCount >= maxRetries) {
            // 最后尝试：即使没有尺寸也初始化
            this.initChartWithResizeObserver(index, container, chart)
            return
          }
          // 容器没有尺寸，延迟后重试
          setTimeout(() => {
            tryInitChart(retryCount + 1, maxRetries)
          }, 150)
          return
        }

        // 容器存在且有尺寸，可以初始化
        this.initChartWithContainer(index, container)
      }

      // 先尝试立即初始化
      this.$nextTick(() => {
        this.$nextTick(() => {
          tryInitChart(0, 30) // 最多重试30次，每次150ms，总共最多4.5秒
        })
      })
    },
    // 使用容器初始化图表的内部方法
    initChartWithContainer(index, container) {
      const chart = this.chartList[index]
      if (!chart || !container) return

      // 使用多种方式检查容器是否有尺寸（更可靠）
      const rect = container.getBoundingClientRect()
      const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
                      (rect.width > 0 && rect.height > 0) ||
                      (container.clientWidth > 0 && container.clientHeight > 0)

      // 再次确认容器有尺寸（双重保险）
      if (!hasSize) {
        // 容器没有尺寸，使用 ResizeObserver 监听
        this.initChartWithResizeObserver(index, container, chart)
        return
      }

      // 如果已经有实例，先销毁
      if (chart.chartInstance) {
        try {
          chart.chartInstance.dispose()
        } catch (e) {
          console.warn('销毁图表实例时出错:', e)
        }
        chart.chartInstance = null
      }

      // 初始化图表实例（确保容器有尺寸）
      try {
        chart.chartInstance = echarts.init(container)
        this.updateChart(index)
      } catch (e) {
        console.error('初始化图表失败:', e)
        // 如果初始化失败，可能是容器尺寸问题，尝试使用 ResizeObserver
        if (e.message && e.message.includes('width or height')) {
          this.initChartWithResizeObserver(index, container, chart)
        }
      }
    },
    // 当容器没有尺寸时，使用 ResizeObserver 监听并初始化
    initChartWithResizeObserver(index, container, chart) {
      if (!container || !chart) return

      // 检查容器是否在可见的tab中
      const isStatisticsTab = this.activeTab === 'statistics'
      if (!isStatisticsTab) {
        // 不在统计tab中，标记为待初始化，等待tab切换
        chart._pendingInit = true
        chart._pendingInitIndex = index
        return
      }

      // 检查容器及其父元素是否可见
      const style = window.getComputedStyle(container)
      const isVisible = style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'

      // 检查父元素
      let parent = container.parentElement
      let parentVisible = true
      while (parent && parent !== document.body) {
        const parentStyle = window.getComputedStyle(parent)
        if (parentStyle.display === 'none' || parentStyle.visibility === 'hidden') {
          parentVisible = false
          break
        }
        parent = parent.parentElement
      }

      if (!isVisible || !parentVisible) {
        // 容器不可见，标记为待初始化，等待可见后再初始化
        chart._pendingInit = true
        chart._pendingInitIndex = index
        return
      }

      // 先检查容器是否有尺寸
      const rect = container.getBoundingClientRect()
      const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
                      (rect.width > 0 && rect.height > 0)

      if (hasSize) {
        // 容器有尺寸，直接初始化
        this.initChartWithContainer(index, container)
        return
      }

      // 容器没有尺寸，使用 ResizeObserver 监听，等待有尺寸后再初始化
      if (typeof ResizeObserver !== 'undefined') {
        const observer = new ResizeObserver((entries) => {
          for (const entry of entries) {
            const target = entry.target
            const targetRect = target.getBoundingClientRect()
            const targetHasSize = (target.offsetWidth > 0 && target.offsetHeight > 0) ||
                                (targetRect.width > 0 && targetRect.height > 0)

            if (targetHasSize && !chart.chartInstance) {
              // 容器有尺寸了，初始化图表
              try {
                this.initChartWithContainer(index, target)
                // 初始化成功后，清理观察者
                if (target._chartResizeObserver) {
                  target._chartResizeObserver.disconnect()
                  delete target._chartResizeObserver
                }
                // 清除待初始化标记
                delete chart._pendingInit
                delete chart._pendingInitIndex
              } catch (e) {
                console.error('图表初始化失败:', e)
              }
            } else if (targetHasSize && chart.chartInstance) {
              // 容器有尺寸且图表已初始化，调整大小
              chart.chartInstance.resize()
            }
          }
        })
        observer.observe(container)
        // 保存观察者引用，以便后续清理
        container._chartResizeObserver = observer

        // 设置超时，如果30秒后还没有尺寸，就放弃（增加等待时间）
        setTimeout(() => {
          if (container._chartResizeObserver === observer && !chart.chartInstance) {
            container._chartResizeObserver.disconnect()
            delete container._chartResizeObserver
            // 输出更详细的调试信息
            const rect = container.getBoundingClientRect()
            const style = window.getComputedStyle(container)
            console.warn(`容器在30秒内仍没有尺寸，放弃初始化图表，索引: ${index}`, {
              offsetWidth: container.offsetWidth,
              offsetHeight: container.offsetHeight,
              clientWidth: container.clientWidth,
              clientHeight: container.clientHeight,
              rectWidth: rect.width,
              rectHeight: rect.height,
              display: style.display,
              visibility: style.visibility,
              opacity: style.opacity,
              activeTab: this.activeTab
            })
          }
        }, 30000) // 增加到30秒
      } else {
        // 不支持 ResizeObserver，使用轮询方式检查
        let checkCount = 0
        const maxChecks = 150 // 30秒 / 200ms = 150次
        const checkInterval = setInterval(() => {
          checkCount++
          const rect = container.getBoundingClientRect()
          const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
                          (rect.width > 0 && rect.height > 0)

          if (hasSize && !chart.chartInstance) {
            clearInterval(checkInterval)
            this.initChartWithContainer(index, container)
            // 清除待初始化标记
            delete chart._pendingInit
            delete chart._pendingInitIndex
          } else if (checkCount >= maxChecks) {
            clearInterval(checkInterval)
            if (!chart.chartInstance) {
              const style = window.getComputedStyle(container)
              console.warn(`容器在30秒内仍没有尺寸，放弃初始化图表，索引: ${index}`, {
                offsetWidth: container.offsetWidth,
                offsetHeight: container.offsetHeight,
                activeTab: this.activeTab,
                display: style.display
              })
            }
          }
        }, 200)
      }
    },
    handleResize() {
      this.chartList.forEach((chart) => {
        if (chart.chartInstance) {
          chart.chartInstance.resize()
        }
      })
    },
    // 打开添加机型弹窗
    handleOpenAddModelDialog(index) {
      this.currentChartIndex = index
      this.addModelDialogVisible = true
      this.initTransferData(index)
    },
    // 初始化穿梭框数据
    initTransferData(chartIndex) {
      const chart = this.chartList[chartIndex]
      if (!chart) {
        return
      }

      // 使用头部搜索结果作为弹窗数据来源
      if (!Array.isArray(this.modelList) || this.modelList.length === 0) {
        this.$message.info('请先在顶部查询机型')
        this.transferData = []
        this.transferSelectedKeys = []
        return
      }

      // 构建穿梭框数据源
      this.transferData = this.modelList.map((model) => {
        const modelId = model.id || model.rowId || model.engineModelID
        const parameterVersion = model.parameterVersion || 1
        const modelKey = `${modelId}_${parameterVersion}`
        const modelName = model.modelName || model.productFullName || '未知机型'

        return {
          key: modelKey,
          label: modelName, // 只显示机型名称，不显示版本号
          modelId: modelId,
          parameterVersion: parameterVersion,
          modelName: modelName,
          // 保存原始数据用于搜索
          productNumber: model.productNumber || '',
          platform: model.platform || '',
          series: model.series || ''
        }
      })

      // 初始化已选中的机型（从图表中获取）
      if (chart.selectedModels && Array.isArray(chart.selectedModels)) {
        this.transferSelectedKeys = chart.selectedModels.map((m) => {
          const version = m.parameterVersion || 1
          return `${m.id}_${version}`
        })
      } else {
        this.transferSelectedKeys = []
      }
    },
    // 穿梭框选择变化处理（限制新选择的机型数量）
    handleTransferChange(value, direction, movedKeys) {
      if (this.currentChartIndex < 0) {
        return
      }

      const chart = this.chartList[this.currentChartIndex]
      if (!chart) {
        return
      }

      // 获取当前已选中的机型key集合
      const currentSelectedKeys = new Set()
      if (chart.selectedModels && Array.isArray(chart.selectedModels)) {
        chart.selectedModels.forEach((m) => {
          const version = m.parameterVersion || 1
          currentSelectedKeys.add(`${m.id}_${version}`)
        })
      }

      // 计算新选择的机型（在value中但不在currentSelectedKeys中）
      const newSelectedKeys = value.filter((key) => !currentSelectedKeys.has(key))

      // 如果是从右侧移除（direction === 'left'），不需要限制
      if (direction === 'left') {
        return
      }

      // 如果是从左侧添加（direction === 'right'），检查新选择的机型数量
      if (direction === 'right' && newSelectedKeys.length > 10) {
        // 恢复到之前的状态（移除超出限制的选择）
        const previousKeys = Array.from(currentSelectedKeys)
        const allowedNewKeys = newSelectedKeys.slice(0, 10)
        this.transferSelectedKeys = [...previousKeys, ...allowedNewKeys]

        this.$message({
          type: 'warning',
          message: '为了避免大量数据的长时间请求，单次选择的新机型上限是10个，查询后，可继续选择。',
          duration: 4000
        })
      }
    },
    // 关闭添加机型弹窗
    handleAddModelDialogClose() {
      this.addModelDialogVisible = false
      this.currentChartIndex = -1
      this.transferSelectedKeys = []
      this.transferData = []
    },
    // 确认添加机型
    handleConfirmAddModel() {
      if (this.transferSelectedKeys.length === 0) {
        this.$message({
          type: 'warning',
          message: '请至少选择一个机型'
        })
        return
      }

      if (this.currentChartIndex < 0) {
        return
      }

      const chart = this.chartList[this.currentChartIndex]
      if (!chart) {
        return
      }

      // 获取当前已选中的机型key集合
      const currentSelectedKeys = new Set()
      if (chart.selectedModels && Array.isArray(chart.selectedModels)) {
        chart.selectedModels.forEach((m) => {
          const version = m.parameterVersion || 1
          currentSelectedKeys.add(`${m.id}_${version}`)
        })
      }

      // 根据选中的key获取机型信息
      const selectedModels = []
      const newSelectedModels = [] // 新选择的机型
      const removedModelIds = new Set() // 被移除的机型ID

      // 找出被移除的机型
      currentSelectedKeys.forEach((key) => {
        if (!this.transferSelectedKeys.includes(key)) {
          const item = this.transferData.find((d) => d.key === key)
          if (item) {
            removedModelIds.add(item.modelId)
          }
        }
      })

      // 处理选中的机型
      this.transferSelectedKeys.forEach((key) => {
        const item = this.transferData.find((d) => d.key === key)
        if (item) {
          const modelInfo = {
            id: item.modelId,
            name: item.modelName,
            parameterVersion: item.parameterVersion
          }
          selectedModels.push(modelInfo)

          // 如果是新选择的机型，添加到新选择列表
          if (!currentSelectedKeys.has(key)) {
            newSelectedModels.push(modelInfo)
          }
        }
      })

      // 更新图表的选中机型
      chart.selectedModels = selectedModels

      // 从缓存中移除被取消选择的机型数据
      if (removedModelIds.size > 0) {
        removedModelIds.forEach((modelId) => {
          if (chart.cachedModelData && chart.cachedModelData[modelId]) {
            delete chart.cachedModelData[modelId]
          }
        })
      }

      // 保存新选择的机型信息，用于后续查询
      chart.newSelectedModels = newSelectedModels

      // 先触发查询，再关闭弹窗，避免 currentChartIndex 被重置
      const chartIndex = this.currentChartIndex
      if (chartIndex >= 0) {
        this.handleChartModelQuery(chartIndex)
      }
      this.handleAddModelDialogClose()
    },
    // 图表机型查询
    handleChartModelQuery(index) {
      const chart = this.chartList[index]
      if (!chart) return

      // 如果没有选择机型，提示用户
      if (!chart.selectedModels || chart.selectedModels.length === 0) {
        this.$message.warning('请先选择机型')
        return
      }

      // 获取新选择的机型（需要查询的机型）
      const newSelectedModels = chart.newSelectedModels || []
      // 如果没有新选择的机型，说明都是已查询过的，直接使用缓存数据更新图表
      if (!newSelectedModels || newSelectedModels.length === 0) {
        // 根据当前选择的机型，从缓存中获取数据并更新图表
        this.updateChartDataFromCache(index)
        this.updateChart(index)
        return
      }

      // 只查询新选择的机型
      const newModelIds = newSelectedModels.map((m) => m.id)
      const request = {
        ...api.GET_CHECK_DATA_CHARTS,
        params: newModelIds, // 只传新选择的机型id数组
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          console.log(resp)
          // 处理返回的数据
          if (resp && resp.data) {
            // 更新Y轴参数选项（支持多种数据格式）
            let newParamOptions = []
            if (resp.data.paramList && Array.isArray(resp.data.paramList)) {
              // 如果返回的是对象，包含 paramList 数组
              newParamOptions = resp.data.paramList.map((paramName) => ({
                label: paramName,
                value: paramName
              }))
            } else if (Array.isArray(resp.data)) {
              // 如果返回的是数组
              newParamOptions = resp.data.map((item) => ({
                label: item.name || item.label || item.parameterName || item,
                value: item.value || item.id || item.parameterName || item
              }))
            }

            // 合并新的参数选项到现有选项中（避免重复）
            if (newParamOptions.length > 0) {
              const existingParamMap = new Map()
              this.yAxisParamOptions.forEach((opt) => {
                existingParamMap.set(opt.value, opt)
              })
              newParamOptions.forEach((opt) => {
                if (!existingParamMap.has(opt.value)) {
                  existingParamMap.set(opt.value, opt)
                }
              })
              this.yAxisParamOptions = Array.from(existingParamMap.values())
              // 更新过滤后的选项为所有选项
              this.filteredYAxisParamOptions = this.yAxisParamOptions
            }

            // 处理返回的数据，按机型ID分组保存到缓存
            const pojosData = resp.data.pojos || []
            console.log('查询返回的数据:', pojosData)
            console.log('新选择的机型:', newSelectedModels)

            if (pojosData.length > 0) {
              // 初始化缓存对象
              if (!chart.cachedModelData) {
                chart.cachedModelData = {}
              }

              // 查询返回的pojosData是一个数组，每个元素代表一个机型的数据
              // 每个元素包含机型的各种属性（modelName, projectName等）和pojos属性（参数列表）
              // 我们需要根据查询时传入的机型ID来匹配和保存数据
              pojosData.forEach((modelData) => {
                // 尝试多种方式获取机型ID
                let modelId = modelData.id || modelData.modelId || modelData.engineModelID || modelData.rowId

                // 如果无法从数据中获取ID，尝试通过机型名称匹配
                if (!modelId) {
                  const modelName = modelData.modelName || modelData.productFullName || ''
                  const matchedModel = newSelectedModels.find((m) => {
                    return m.name === modelName || String(m.id) === String(modelData.id)
                  })
                  if (matchedModel) {
                    modelId = matchedModel.id
                  }
                }

                // 如果找到了机型ID，保存到缓存
                if (modelId) {
                  const modelIdStr = String(modelId)
                  // 如果该机型已有缓存数据，合并数据（避免重复）
                  if (chart.cachedModelData[modelIdStr]) {
                    // 检查是否已存在相同的数据，避免重复添加
                    const exists = chart.cachedModelData[modelIdStr].some((existing) => {
                      return JSON.stringify(existing) === JSON.stringify(modelData)
                    })
                    if (!exists) {
                      chart.cachedModelData[modelIdStr].push(modelData)
                    }
                  } else {
                    chart.cachedModelData[modelIdStr] = [modelData]
                  }
                  console.log(`保存机型数据到缓存: ${modelIdStr}`, modelData)
                } else {
                  console.warn('无法匹配机型ID，数据:', modelData)
                }
              })

              console.log('缓存数据:', chart.cachedModelData)
            }

            // 清空新选择的机型标记（查询完成后）
            chart.newSelectedModels = []
            // 根据当前选择的机型，从缓存中获取数据并更新图表
            this.updateChartDataFromCache(index)

            // 更新当前图表
            this.updateChart(index)
          }
        })
        .asyncErrorCatch((err) => {
          console.error('查询失败:', err)
          this.$message.error('查询失败，请重试')
        })
    },
    // 根据当前选择的机型，从缓存中获取数据并更新chartDataList
    updateChartDataFromCache(index) {
      const chart = this.chartList[index]
      if (!chart || !chart.selectedModels || !chart.cachedModelData) {
        if (chart) {
          chart.chartDataList = []
        }
        return
      }

      // 根据当前选择的机型，从缓存中获取数据
      // 确保ID类型一致（都转为字符串进行比较）
      const selectedModelIds = new Set(chart.selectedModels.map((m) => String(m.id)))
      const chartDataList = []

      console.log('从缓存更新图表数据 - 选中的机型ID:', Array.from(selectedModelIds))
      console.log('缓存中的机型ID:', Object.keys(chart.cachedModelData))

      // 遍历缓存的机型数据，只添加当前选中的机型数据
      Object.keys(chart.cachedModelData).forEach((modelId) => {
        // 确保ID类型一致
        const modelIdStr = String(modelId)
        if (selectedModelIds.has(modelIdStr)) {
          const modelData = chart.cachedModelData[modelId]
          if (Array.isArray(modelData)) {
            chartDataList.push(...modelData)
          } else {
            // 如果不是数组，直接添加
            chartDataList.push(modelData)
          }
        }
      })

      console.log('更新后的chartDataList:', chartDataList)
      chart.chartDataList = chartDataList
    },
    // 图表机型重置
    handleChartModelReset(index) {
      const chart = this.chartList[index]
      if (chart) {
        // 清空所有选中的机型
        chart.selectedModels = []
        // 清空新选择的机型标记
        chart.newSelectedModels = []
        // 清空图表数据
        chart.chartDataList = []
        // 清空缓存数据
        chart.cachedModelData = {}
        // 更新图表
        this.updateChart(index)
      }
    },
    updateChart(index) {
      const chart = this.chartList[index]
      if (!chart || !chart.chartInstance) return

      if (typeof chart.scatterTrendline === 'undefined') {
        this.$set(chart, 'scatterTrendline', false)
      }

      // 根据选择的X轴获取数据
      const xAxisValue = chart.xAxis || ''
      const xAxisOption = this.xAxisOptions.find((opt) => opt.value === xAxisValue)
      const xAxisLabel = xAxisOption ? xAxisOption.label : ''

      // 从查询结果中获取X轴数据
      let xAxisData = []
      const xAxisDataMap = new Map() // 用于去重和合并数据

      // 使用当前图表的数据列表（已经根据选择的机型查询过了）
      let filteredDataList = chart.chartDataList || []

      if (filteredDataList && filteredDataList.length > 0) {
        // 遍历查询结果，提取X轴数据
        filteredDataList.forEach((model) => {
          let xAxisValueItem = ''
          if (xAxisValue === 'projectName') {
            xAxisValueItem = model.projectName || ''
          } else if (xAxisValue === 'modelName') {
            xAxisValueItem = model.modelName || ''
          } else if (xAxisValue === 'plate') {
            xAxisValueItem = model.plate || ''
          } else if (xAxisValue === 'platform') {
            xAxisValueItem = model.platform || ''
          } else if (xAxisValue === 'series') {
            xAxisValueItem = model.series || ''
          } else if (xAxisValue === 'emission') {
            xAxisValueItem = model.emission || ''
          } else if (xAxisValue === 'burnType') {
            xAxisValueItem = model.burnType || ''
          } else if (xAxisValue === 'engineCapacity') {
            xAxisValueItem = model.engineCapacity || ''
          }

          if (xAxisValueItem) {
            // 如果还没有这个X轴值，创建新的数据项
            if (!xAxisDataMap.has(xAxisValueItem)) {
              xAxisDataMap.set(xAxisValueItem, {
                xValue: xAxisValueItem,
                parameters: model.pojos || []
              })
            } else {
              // 如果已存在，合并参数数据
              const existing = xAxisDataMap.get(xAxisValueItem)
              existing.parameters = existing.parameters.concat(model.pojos || [])
            }
          }
        })

        // 转换为数组并排序
        xAxisData = Array.from(xAxisDataMap.keys())
      }

      // 如果没有数据，使用默认数据
      if (xAxisData.length === 0) {
        if (xAxisValue === 'engineCapacity') {
          // 排量是范围值，需要特殊处理
          const min = this.searchPanelValue.engineCapacityMin || 0
          const max = this.searchPanelValue.engineCapacityMax || 100
          const step = (max - min) / 10
          xAxisData = []
          for (let i = 0; i <= 10; i++) {
            const value = min + step * i
            xAxisData.push(value.toFixed(1))
          }
        } else {
          // xAxisData = this.getDefaultXAxisData(xAxisValue)
        }
      }

      // 生成Y轴数据（从查询结果中提取）
      const selectedParams = Array.isArray(chart.yAxisParam) ? chart.yAxisParam : []
      const paramDataMap = {}

      // 判断X轴去重后数量是否少于查询结果数量（说明有重复的X轴值）
      const hasDuplicateXValues = xAxisData.length < this.chartDataList.length

      selectedParams.forEach((paramName) => {
        // 为每个参数生成数据数组
        const paramData = []
        xAxisData.forEach((xValue) => {
          // 查找该X轴值对应的参数值
          let paramValue = null
          if (xAxisDataMap.has(xValue)) {
            const dataItem = xAxisDataMap.get(xValue)
            // 在参数列表中查找所有匹配的parameterName（可能有多个相同X轴值的数据项）
            const matchedParams = dataItem.parameters.filter((p) => p.parameterName === paramName)

            if (matchedParams && matchedParams.length > 0) {
              if (hasDuplicateXValues) {
                // 如果有重复的X轴值，累加所有匹配的参数值
                let sum = 0
                let hasValidNumber = false
                matchedParams.forEach((param) => {
                  if (param.parameterValue !== undefined && param.parameterValue !== null) {
                    const numValue = parseFloat(param.parameterValue)
                    if (!isNaN(numValue)) {
                      sum += numValue
                      hasValidNumber = true
                    }
                  }
                })
                paramValue = hasValidNumber ? sum : null
              } else {
                // 没有重复的X轴值，使用第一个匹配的参数值
                const matchedParam = matchedParams[0]
                if (
                  matchedParam.parameterValue !== undefined &&
                  matchedParam.parameterValue !== null
                ) {
                  const numValue = parseFloat(matchedParam.parameterValue)
                  paramValue = isNaN(numValue) ? matchedParam.parameterValue : numValue
                }
              }
            }
          }
          // 如果没有值或者null就是0
          paramData.push(paramValue === null || paramValue === undefined ? 0 : paramValue)
        })
        paramDataMap[paramName] = paramData
      })

      const series = []
      const legendData = []
      const chartType = chart.chartType
      const isScatter = chartType === 'scatter'
      const isBar = chartType === 'bar'
      const isPie = chartType === 'pie'
      const showScatterTrendline = isScatter && !!chart.scatterTrendline

      // 如果选择了公式，计算公式结果
      let formulaData = null
      if (chart.yAxisFormula) {
        const selectedFormula = this.savedFormulas.find((f) => f.id === chart.yAxisFormula)
        if (selectedFormula) {
          // 兼容新格式（formulaItems）和旧格式（param1, operator, param2）
          const hasNewFormat = selectedFormula.formulaItems && Array.isArray(selectedFormula.formulaItems) && selectedFormula.formulaItems.length > 0
          const hasOldFormat = selectedFormula.param1 && selectedFormula.param2 && selectedFormula.operator
          
          if (hasNewFormat || hasOldFormat) {
          formulaData = this.calculateFormula(
            selectedFormula,
            xAxisData,
            xAxisDataMap,
            hasDuplicateXValues
          )
          // 处理公式数据中的null值
          if (formulaData && formulaData.length > 0) {
            formulaData = formulaData.map((val) => (val === null || val === undefined ? 0 : val))
            }
          }
        }
      }

      // 数据从高到低排序
      if (xAxisData.length > 0 && selectedParams.length > 0) {
        // 创建一个索引数组，用于排序
        const indices = xAxisData.map((_, index) => index)

        // 根据第一个参数的值从高到低排序（如果多个参数，可以改为总和）
        const firstParamData = paramDataMap[selectedParams[0]] || []
        indices.sort((a, b) => {
          const valueA = firstParamData[a] || 0
          const valueB = firstParamData[b] || 0
          return valueB - valueA // 从高到低
        })

        // 重新排列xAxisData和所有paramData
        xAxisData = indices.map((i) => xAxisData[i])
        selectedParams.forEach((paramName) => {
          const originalData = paramDataMap[paramName] || []
          paramDataMap[paramName] = indices.map((i) => originalData[i] || 0)
        })

        // 如果有公式数据，也需要重新排列
        if (formulaData && formulaData.length > 0) {
          formulaData = indices.map((i) => formulaData[i] || 0)
        }
      }

      // 获取参数名称映射
      const getParamLabel = (paramValue) => {
        const paramOption = this.yAxisParamOptions.find((opt) => opt.value === paramValue)
        return paramOption ? paramOption.label : paramValue
      }

      if (isPie) {
        const pieData = []
        const pieColors = ['#67C23A', '#E6A23C', '#F56C6C', '#409EFF', '#909399']

        selectedParams.forEach((paramValue, index) => {
          const paramData = paramDataMap[paramValue] || []
          const avgValue =
            paramData.length > 0
              ? paramData.reduce((sum, val) => sum + (val || 0), 0) / paramData.length
              : 0
          const paramLabel = getParamLabel(paramValue)
          pieData.push({ value: avgValue, name: paramLabel })
          legendData.push(paramLabel)
        })

        const pieOption = {
          title: { show: false },
          tooltip: {
            trigger: 'item',
            formatter(params) {
              const value = parseFloat(params.value).toFixed(2)
              return `${params.seriesName}<br/>${params.name}: ${value} `
            }
          },
          legend: {
            type: 'scroll',
            data: legendData,
            top: 5,
            left: 'center',
            height: '40px',
            itemHeight: 18,
            itemGap: 12,
            padding: [15, 10, 10, 10],
            textStyle: {
              fontSize: 14,
              lineHeight: 18
            }
          },
          series: [
            {
              name: '数据分布',
              type: 'pie',
              radius: ['40%', '70%'],
              avoidLabelOverlap: false,
              itemStyle: {
                borderRadius: 10,
                borderColor: '#fff',
                borderWidth: 2
              },
              label: {
                show: true,
                formatter(params) {
                  return `${params.name}: ${parseFloat(params.value).toFixed(2)}%`
                }
              },
              emphasis: {
                label: {
                  show: true,
                  fontSize: '16',
                  fontWeight: 'bold'
                }
              },
              labelLine: {
                show: true
              },
              data: pieData.map((item, idx) => ({
                ...item,
                itemStyle: {
                  color: pieColors[idx % pieColors.length]
                }
              }))
            }
          ]
        }

        chart.chartInstance.setOption(pieOption, true)
        return
      }

      // 参数颜色配置
      const paramColors = [
        '#67C23A',
        '#E6A23C',
        '#F56C6C',
        '#409EFF',
        '#909399',
        '#E4E7ED',
        '#C0C4CC'
      ]
      const paramSymbols = ['circle', 'rect', 'triangle', 'diamond', 'pin', 'arrow']

      // 为每个选中的参数创建系列
      selectedParams.forEach((paramValue, index) => {
        const paramData = paramDataMap[paramValue] || []
        const paramLabel = getParamLabel(paramValue)
        const color = paramColors[index % paramColors.length]
        const symbol = paramSymbols[index % paramSymbols.length]

        const paramSeries = {
          name: paramLabel,
          type: isBar ? 'bar' : isScatter ? 'scatter' : 'line',
          data: paramData,
          symbol: isScatter ? symbol : 'circle',
          symbolSize: isScatter ? 8 : 6,
          itemStyle: { color: color },
          lineStyle: { color: color, width: 2 }
        }

        // 折线图不带有阴影（已移除areaStyle配置）

        series.push(paramSeries)
        legendData.push(paramLabel)

        // 添加趋势线（仅散点图）
        if (showScatterTrendline) {
          series.push({
            name: `趋势线 (${paramLabel})`,
            type: 'line',
            data: paramData,
            lineStyle: {
              color: color,
              type: 'solid',
              width: 2
            },
            symbol: 'none',
            smooth: true
          })
          legendData.push(`趋势线 (${paramLabel})`)
        }
      })

      // 如果选择了公式，添加公式计算结果系列
      if (formulaData && formulaData.length > 0) {
        // 确保公式数据长度与X轴数据一致
        const finalFormulaData = []
        for (let i = 0; i < xAxisData.length; i++) {
          if (i < formulaData.length) {
            const val = formulaData[i]
            finalFormulaData.push(val === null || val === undefined || isNaN(val) ? 0 : val)
          } else {
            finalFormulaData.push(0)
          }
        }

        const selectedFormula = this.savedFormulas.find((f) => f.id === chart.yAxisFormula)
        const formulaName = selectedFormula ? selectedFormula.name : '公式'
        const formulaSeries = {
          name: formulaName,
          type: chartType === 'bar' ? 'bar' : chartType === 'scatter' ? 'scatter' : 'line',
          data: finalFormulaData,
          itemStyle: { color: '#F56C6C' }
        }

        // 柱状图配置：与其他系列保持一致的样式，让ECharts自动并排显示
        if (chartType === 'bar') {
          // 柱状图不需要特殊配置，ECharts会自动处理多系列的并排显示
        } else if (chartType === 'line') {
          // 折线图使用虚线样式
          formulaSeries.lineStyle = {
            color: '#F56C6C',
            type: 'dashed',
            width: 2
          }
          formulaSeries.symbol = 'circle'
          formulaSeries.symbolSize = 6
        } else if (chartType === 'scatter') {
          // 散点图配置
          formulaSeries.symbol = 'diamond'
          formulaSeries.symbolSize = 8
        }

        // 确保公式系列与其他系列一起显示，不覆盖其他系列
        series.push(formulaSeries)
        legendData.push(formulaName)
      }

      // 自定义点处理
      if (
        chart.customPointX !== null &&
        chart.customPointX !== '' &&
        chart.customPointY !== null &&
        chart.customPointY !== ''
      ) {
        const xValue = chart.customPointX
        const yValue = chart.customPointY
        // 查找X轴数据中对应的索引
        const xIndex = xAxisData.findIndex((item) => {
          if (xAxisValue === 'engineCapacity') {
            return Math.abs(parseFloat(item) - parseFloat(xValue)) < 0.1
          }
          return item === xValue || item.toString() === xValue.toString()
        })
        const yMin = chart.yAxisMin !== null && chart.yAxisMin !== '' ? chart.yAxisMin : 0
        const yMax = chart.yAxisMax !== null && chart.yAxisMax !== '' ? chart.yAxisMax : 100

        if (xIndex !== -1 && yValue >= yMin && yValue <= yMax) {
          const customPointData = []
          for (let i = 0; i < xAxisData.length; i++) {
            if (i === xIndex) {
              customPointData.push(yValue)
            } else {
              customPointData.push(null)
            }
          }

          series.push({
            name: '自定义点',
            type: 'scatter',
            data: customPointData,
            symbol: 'circle',
            symbolSize: 12,
            itemStyle: {
              color: '#409EFF'
            },
            zlevel: 10
          })
          legendData.push('自定义点')
        }
      }

      const option = {
        title: { show: false },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'cross'
          },
          formatter(params) {
            if (Array.isArray(params)) {
              let result = `${params[0].axisValue}<br/>`
              params.forEach((item) => {
                if (item.value !== undefined && item.value !== null && item.value !== '') {
                  result += `${item.marker}${item.seriesName}: ${item.value}<br/>`
                }
              })
              return result
            }
            if (params.value !== undefined && params.value !== null && params.value !== '') {
              return `${params.seriesName}<br/>${params.marker}${params.name}: ${params.value}`
            }
            return ''
          }
        },
        legend: {
          type: 'scroll',
          data: legendData,
          top: 5,
          height: '40px',
          left: 'center',
          itemHeight: 18,
          itemGap: 12,
          padding: [15, 10, 10, 10],
          textStyle: {
            fontSize: 14,
            lineHeight: 18
          }
        },
        grid: {
          left: '3%',
          right: '60px',
          bottom: '15%',
          top: legendData.length > 0 ? '22%' : '3%',
          containLabel: true
        },
        dataZoom: [
          {
            type: 'slider',
            xAxisIndex: 0,
            start: 0,
            end: 100,
            bottom: 10,
            height: 20,
            handleIcon:
              'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.2,10.8,24.1,24.1,24.1C44.2,51.7,55,40.8,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.6-0.4,1-1,1H26c-0.6,0-1-0.4-1-1s0.4-1,1-1h9.9C36.5,34.8,36.9,35.2,36.9,35.8z',
            handleSize: '80%',
            handleStyle: {
              color: '#fff',
              shadowBlur: 3,
              shadowColor: 'rgba(0, 0, 0, 0.6)',
              shadowOffsetX: 2,
              shadowOffsetY: 2
            },
            textStyle: {
              color: '#333'
            },
            borderColor: '#ccc',
            fillerColor: 'rgba(64, 158, 255, 0.2)',
            dataBackground: {
              lineStyle: {
                color: '#409EFF',
                width: 1
              },
              areaStyle: {
                color: 'rgba(64, 158, 255, 0.1)'
              }
            },
            selectedDataBackground: {
              lineStyle: {
                color: '#409EFF',
                width: 2
              },
              areaStyle: {
                color: 'rgba(64, 158, 255, 0.3)'
              }
            }
          },
          {
            type: 'inside',
            xAxisIndex: 0,
            start: 0,
            end: 100
          }
        ],
        xAxis: {
          type: 'category',
          data: xAxisData,
          name: xAxisLabel,
          nameTextStyle: {
            color: '#000'
          },
          boundaryGap: isBar ? true : [0.05, 0.05],
          axisLabel: {
            color: '#000'
          },
          axisLine: {
            lineStyle: {
              color: '#DCDFE6'
            }
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: true,
            lineStyle: {
              type: 'dashed',
              color: '#E4E7ED'
            }
          }
        },
        yAxis: (() => {
          const yMin = chart.yAxisMin !== null && chart.yAxisMin !== '' ? chart.yAxisMin : 0
          const yMax = chart.yAxisMax !== null && chart.yAxisMax !== '' ? chart.yAxisMax : 100
          const range = yMax - yMin
          // 计算最大间隔，确保最多显示10个刻度（9个分割段）
          const maxInterval = range > 0 ? Math.ceil(range / 9) : undefined

          return {
            type: 'value',
            min: yMin,
            max: yMax,
            splitNumber: 9, // 最多显示10个刻度（9个分割段 = 10个刻度点）
            maxInterval: maxInterval, // 限制最大间隔，确保最多显示10个刻度
            axisLabel: {
              formatter: '{value}',
              color: '#000'
            },
            axisLine: {
              lineStyle: {
                color: '#DCDFE6'
              }
            },
            splitLine: {
              show: true,
              lineStyle: {
                type: 'dashed',
                color: '#E4E7ED'
              }
            }
          }
        })(),
        series
      }

      chart.chartInstance.setOption(option, true)
    },
    // 获取默认X轴数据（当没有搜索值时使用）
    getDefaultXAxisData(xAxisValue) {
      // 根据不同的X轴选项返回默认数据
      switch (xAxisValue) {
        case 'projectName':
          return ['项目1', '项目2', '项目3', '项目4', '项目5']
        case 'modelName':
          return ['型号1', '型号2', '型号3', '型号4', '型号5']
        case 'plate':
          return ['板块1', '板块2', '板块3', '板块4', '板块5']
        case 'platform':
          return ['平台1', '平台2', '平台3', '平台4', '平台5']
        case 'series':
          return ['系列1', '系列2', '系列3', '系列4', '系列5']
        case 'emission':
          return ['排放1', '排放2', '排放3', '排放4', '排放5']
        case 'burnType':
          return ['类型1', '类型2', '类型3', '类型4', '类型5']
        case 'engineCapacity':
          return ['1.0', '1.5', '2.0', '2.5', '3.0', '3.5', '4.0', '4.5', '5.0']
        default:
          return ['数据1', '数据2', '数据3', '数据4', '数据5']
      }
    },
    // 生成参数数据（假数据）
    generateParamData(length, paramValue) {
      // 根据参数值生成不同的假数据模式
      const baseValue = paramValue.charCodeAt ? paramValue.charCodeAt(0) % 100 : 50
      const data = []
      for (let i = 0; i < length; i++) {
        // 生成随机但有一定规律的数据
        const value = baseValue + Math.sin(i * 0.5) * 20 + Math.random() * 10
        data.push(Math.round(value * 100) / 100)
      }
      return data
    },
    // 将十六进制颜色转换为rgba
    hexToRgba(hex, alpha) {
      const r = parseInt(hex.slice(1, 3), 16)
      const g = parseInt(hex.slice(3, 5), 16)
      const b = parseInt(hex.slice(5, 7), 16)
      return `rgba(${r}, ${g}, ${b}, ${alpha})`
    },
    // 获取自定义点X坐标的占位符文本
    getCustomPointXPlaceholder(chart) {
      if (!chart || !chart.xAxis) {
        return 'X坐标'
      }
      const xAxisOption = this.xAxisOptions.find((opt) => opt.value === chart.xAxis)
      const label = xAxisOption ? xAxisOption.label : ''
      return `X坐标(${label})`
    },
    handleFormulaSelectChange(index) {
      const chart = this.chartList[index]
      if (!chart) return

      // 如果选择了公式，更新图表
      this.updateChart(index)
    },
    startEditTitle(index) {
      const chart = this.chartList[index]
      if (chart) {
        chart.isEditingTitle = true
        this.$nextTick(() => {
          const refName = `titleInput-${index}`
          const inputRef = this.$refs[refName]
          if (inputRef) {
            const input = Array.isArray(inputRef) ? inputRef[0] : inputRef
            if (input && input.$el && input.$el.querySelector('input')) {
              input.$el.querySelector('input').focus()
            }
          }
        })
      }
    },
    // 获取公式预览文本
    // 处理选中参数变化
    handleSelectedParamsChange() {
      // 限制最多选择5个参数
      if (this.formulaFormData.selectedParams.length > 5) {
        this.$message.warning('最多只能选择5个参数')
        this.formulaFormData.selectedParams = this.formulaFormData.selectedParams.slice(0, 5)
      }
      // 根据选中的参数更新可用参数列表
      this.formulaFormData.availableParams = this.formulaFormData.selectedParams.map(paramValue => {
        const option = this.yAxisParamOptions.find(opt => opt.value === paramValue)
        return option || { label: paramValue, value: paramValue }
      })
    },
    // 添加数字到构建区（可拖拽数字列表）
    addNumberToBuilder() {
      if (this.formulaFormData.inputNumber === null || this.formulaFormData.inputNumber === '') {
        this.$message.warning('请输入数字')
        return
      }
      const numValue = parseFloat(this.formulaFormData.inputNumber)
      if (isNaN(numValue)) {
        this.$message.warning('请输入有效的数字')
        return
      }
      // 添加到最近使用的数字列表（最多保留5个）
      // 如果数字已存在，先移除再添加到最前面
      const existingIndex = this.formulaFormData.recentNumbers.indexOf(numValue)
      if (existingIndex !== -1) {
        this.formulaFormData.recentNumbers.splice(existingIndex, 1)
      }
      this.formulaFormData.recentNumbers.unshift(numValue)
      if (this.formulaFormData.recentNumbers.length > 5) {
        this.formulaFormData.recentNumbers = this.formulaFormData.recentNumbers.slice(0, 5)
      }
      // 清空输入框
      this.formulaFormData.inputNumber = null
      this.$message.success('数字已添加到构建区，可拖拽到公式预览区域')
    },
    // 拖拽开始
    handleDragStart(event, type, value, label) {
      event.dataTransfer.setData('application/json', JSON.stringify({
        type: type,
        value: value,
        label: label
      }))
      // 设置为copy模式，确保参数可以重复使用（不会从源位置移除）
      event.dataTransfer.effectAllowed = 'copy'
      // 添加拖拽时的视觉反馈
      if (event.target) {
        event.target.style.opacity = '0.5'
      }
    },
    // 拖拽结束
    handleDragEnd(event) {
      // 恢复元素的透明度，确保参数仍然可见
      if (event.target) {
        event.target.style.opacity = '1'
      }
    },
    // 拖拽进入预览区域
    handleDragEnter(event) {
      event.preventDefault()
      this.isDraggingOver = true
    },
    // 拖拽离开预览区域
    handleDragLeave(event) {
      event.preventDefault()
      // 只有当离开的是预览容器本身时才设置为false
      if (event.target.classList.contains('preview-container')) {
        this.isDraggingOver = false
      }
    },
    // 拖拽放置（从外部拖入预览区域）
    handleDrop(event) {
      event.preventDefault()
      this.isDraggingOver = false
      // 如果是从预览区域内部拖拽，不处理
      if (this.draggingPreviewIndex !== -1) {
        return
      }
      try {
        const data = JSON.parse(event.dataTransfer.getData('application/json'))
        if (data && data.type && data.value && data.label) {
          this.formulaFormData.formulaItems.push({
            type: data.type,
            value: data.value,
            label: data.label
          })
        }
      } catch (e) {
        console.error('拖拽数据解析失败:', e)
      }
    },
    // 预览区域拖拽开始
    handlePreviewDragStart(event, index) {
      this.draggingPreviewIndex = index
      event.dataTransfer.effectAllowed = 'move'
      event.dataTransfer.setData('text/plain', String(index))
      // 添加拖拽时的视觉反馈
      if (event.target) {
        event.target.style.opacity = '0.5'
      }
    },
    // 预览区域拖拽悬停
    handlePreviewDragOver(event, index) {
      event.preventDefault()
      if (this.draggingPreviewIndex !== -1 && this.draggingPreviewIndex !== index) {
        this.dragOverPreviewIndex = index
      }
    },
    // 预览区域拖拽进入
    handlePreviewDragEnter(event, index) {
      event.preventDefault()
      if (this.draggingPreviewIndex !== -1 && this.draggingPreviewIndex !== index) {
        this.dragOverPreviewIndex = index
      }
    },
    // 预览区域拖拽离开
    handlePreviewDragLeave(event) {
      // 只有当离开的是预览项本身时才清除
      if (event.target.classList.contains('preview-item')) {
        this.dragOverPreviewIndex = -1
      }
    },
    // 预览区域拖拽放置（排序）
    handlePreviewDrop(event, targetIndex) {
      event.preventDefault()
      event.stopPropagation()
      
      if (this.draggingPreviewIndex === -1 || this.draggingPreviewIndex === targetIndex) {
        this.draggingPreviewIndex = -1
        this.dragOverPreviewIndex = -1
        return
      }

      // 执行排序
      const items = [...this.formulaFormData.formulaItems]
      const draggedItem = items[this.draggingPreviewIndex]
      
      // 移除原位置的项
      items.splice(this.draggingPreviewIndex, 1)
      
      // 计算新位置
      let insertIndex = targetIndex
      // 如果从前面拖到后面，目标索引需要减1（因为已经移除了一个元素）
      if (this.draggingPreviewIndex < targetIndex) {
        insertIndex = targetIndex - 1
      }
      
      // 插入到目标位置之后（即 insertIndex + 1）
      items.splice(insertIndex + 1, 0, draggedItem)
      
      // 更新数组
      this.formulaFormData.formulaItems = items
      
      // 重置状态
      this.draggingPreviewIndex = -1
      this.dragOverPreviewIndex = -1
    },
    // 预览区域拖拽结束
    handlePreviewDragEnd(event) {
      // 恢复元素的透明度
      if (event.target) {
        event.target.style.opacity = '1'
      }
      // 重置状态
      this.draggingPreviewIndex = -1
      this.dragOverPreviewIndex = -1
    },
    // 移除公式项
    removeFormulaItem(index) {
      this.formulaFormData.formulaItems.splice(index, 1)
    },
    // 清空公式
    clearFormula() {
      this.formulaFormData.formulaItems = []
    },
    // 添加括号
    addBracket(bracket) {
      this.formulaFormData.formulaItems.push({
        type: 'bracket',
        value: bracket,
        label: bracket
      })
    },
    // 验证公式项是否有效
    isFormulaItemsValid() {
      const items = this.formulaFormData.formulaItems
      if (!items || items.length === 0) {
        return false
      }
      // 至少需要一个参数
      const hasParam = items.some(item => item.type === 'param')
      if (!hasParam) {
        return false
      }
      // 基本语法检查：不能以运算符开头或结尾
      if (items.length > 0) {
        const firstItem = items[0]
        const lastItem = items[items.length - 1]
        if (firstItem.type === 'operator' || lastItem.type === 'operator') {
          return false
        }
      }
      return true
    },
    handleEditFormula(index) {
      this.currentFormulaChartIndex = index
      const chart = this.chartList[index]
      if (!chart) return

      // 如果图表已选择了公式，则编辑该公式；否则创建新公式
      if (chart.yAxisFormula) {
        // 编辑已存在的公式
        const existingFormula = this.savedFormulas.find((f) => f.id === chart.yAxisFormula)
        if (existingFormula) {
          this.currentFormulaId = existingFormula.id
          // 兼容旧格式的公式
          if (existingFormula.formulaItems) {
          this.formulaFormData = {
            name: existingFormula.name || '',
              selectedParams: existingFormula.formulaItems
                .filter(item => item.type === 'param')
                .map(item => item.value),
              availableParams: [],
              formulaItems: JSON.parse(JSON.stringify(existingFormula.formulaItems)),
              inputNumber: null,
              recentNumbers: existingFormula.formulaItems
                .filter(item => item.type === 'number')
                .map(item => parseFloat(item.value))
                .filter(num => !isNaN(num))
                .slice(0, 5)
            }
          } else {
            // 旧格式转换为新格式
            const oldItems = []
            if (existingFormula.param1) {
              const param1Option = this.yAxisParamOptions.find(opt => opt.value === existingFormula.param1)
              oldItems.push({
                type: 'param',
                value: existingFormula.param1,
                label: param1Option ? param1Option.label : existingFormula.param1
              })
            }
            if (existingFormula.operator) {
              const opOption = this.formulaOperators.find(opt => opt.value === existingFormula.operator)
              oldItems.push({
                type: 'operator',
                value: existingFormula.operator,
                label: opOption ? opOption.label : existingFormula.operator
              })
            }
            if (existingFormula.param2) {
              const param2Option = this.yAxisParamOptions.find(opt => opt.value === existingFormula.param2)
              oldItems.push({
                type: 'param',
                value: existingFormula.param2,
                label: param2Option ? param2Option.label : existingFormula.param2
              })
            }
            this.formulaFormData = {
              name: existingFormula.name || '',
              selectedParams: [existingFormula.param1, existingFormula.param2].filter(Boolean),
              availableParams: [],
              formulaItems: oldItems,
              inputNumber: null,
              recentNumbers: []
            }
          }
          this.handleSelectedParamsChange()
        } else {
          // 如果找不到公式，创建新的
          this.currentFormulaId = null
          this.formulaFormData = {
            name: '',
            selectedParams: [],
            availableParams: [],
            formulaItems: []
          }
        }
      } else {
        // 创建新公式
        this.currentFormulaId = null
        this.formulaFormData = {
          name: '',
          selectedParams: [],
          availableParams: [],
          formulaItems: [],
          inputNumber: null,
          recentNumbers: []
        }
      }

      this.formulaDialogVisible = true
    },
    handleSaveFormula() {
      // 验证公式
      if (!this.isFormulaValid) {
        this.$message.warning('请完整填写公式信息，公式至少需要一个参数且不能以运算符开头或结尾')
        return
      }

      let formulaId = this.currentFormulaId

      if (formulaId) {
        // 修改已存在的公式
        const formulaIndex = this.savedFormulas.findIndex((f) => f.id === formulaId)
        if (formulaIndex >= 0) {
          this.savedFormulas[formulaIndex] = {
            ...this.savedFormulas[formulaIndex],
            name: this.formulaFormData.name.trim(),
            formulaItems: JSON.parse(JSON.stringify(this.formulaFormData.formulaItems))
          }
        }
      } else {
        // 创建新公式
        formulaId = `formula_${this.formulaIdCounter++}`
        this.savedFormulas.push({
          id: formulaId,
          name: this.formulaFormData.name.trim(),
          formulaItems: JSON.parse(JSON.stringify(this.formulaFormData.formulaItems))
        })
      }

      // 将公式应用到当前图表
      if (this.currentFormulaChartIndex >= 0) {
        const chart = this.chartList[this.currentFormulaChartIndex]
        if (chart) {
          chart.yAxisFormula = formulaId
          this.updateChart(this.currentFormulaChartIndex)
        }
      }

      this.handleFormulaDialogClose()
    },
    // 关闭公式弹窗
    handleFormulaDialogClose() {
      this.formulaDialogVisible = false
      this.currentFormulaChartIndex = -1
      this.currentFormulaId = null
      this.formulaFormData = {
        name: '',
        selectedParams: [],
        availableParams: [],
        formulaItems: [],
        inputNumber: null,
        recentNumbers: []
      }
    },
    // 计算公式结果（新格式：formulaItems数组）
    calculateFormula(formula, xAxisData, xAxisDataMap, hasDuplicateXValues = false) {
      // 兼容旧格式
      if (!formula) {
        return []
      }

      // 如果是旧格式，转换为新格式
      let formulaItems = []
      if (formula.formulaItems && Array.isArray(formula.formulaItems)) {
        formulaItems = formula.formulaItems
      } else if (formula.param1 && formula.param2 && formula.operator) {
        // 旧格式：param1 operator param2
        const param1Option = this.yAxisParamOptions.find(opt => opt.value === formula.param1)
        const param2Option = this.yAxisParamOptions.find(opt => opt.value === formula.param2)
        const opOption = this.formulaOperators.find(opt => opt.value === formula.operator)
        formulaItems = [
          { type: 'param', value: formula.param1, label: param1Option ? param1Option.label : formula.param1 },
          { type: 'operator', value: formula.operator, label: opOption ? opOption.label : formula.operator },
          { type: 'param', value: formula.param2, label: param2Option ? param2Option.label : formula.param2 }
        ]
      } else {
        return []
      }

      if (formulaItems.length === 0) {
        return []
      }

      const formulaData = []

      xAxisData.forEach((xValue) => {
        // 为每个X轴值计算公式结果
        let result = null

        try {
          // 构建表达式并计算
          result = this.evaluateFormulaExpression(formulaItems, xValue, xAxisDataMap, hasDuplicateXValues)
        } catch (err) {
          console.error('计算公式失败:', err)
          result = null
        }

        formulaData.push(result)
      })

      return formulaData
    },
    // 计算表达式值（支持括号、加减乘除）
    evaluateFormulaExpression(formulaItems, xValue, xAxisDataMap, hasDuplicateXValues) {
      // 将中缀表达式转换为后缀表达式（逆波兰表达式）
      const postfix = this.infixToPostfix(formulaItems, xValue, xAxisDataMap, hasDuplicateXValues)
      // 计算后缀表达式
      return this.evaluatePostfix(postfix)
    },
    // 中缀表达式转后缀表达式
    infixToPostfix(formulaItems, xValue, xAxisDataMap, hasDuplicateXValues) {
      const output = []
      const operators = []
      const precedence = {
        '+': 1,
        '-': 1,
        '*': 2,
        '/': 2
      }

      for (let i = 0; i < formulaItems.length; i++) {
        const item = formulaItems[i]

        if (item.type === 'param') {
          // 参数：获取实际值并加入输出
          const paramValue = this.getParamValueFromData(
            item.value,
            xValue,
            xAxisDataMap,
            hasDuplicateXValues
          )
          if (paramValue === null || paramValue === undefined) {
            return null // 参数值缺失，返回null
          }
          const numValue = parseFloat(paramValue)
          if (isNaN(numValue)) {
            return null // 参数值不是数字，返回null
          }
          output.push(numValue)
        } else if (item.type === 'number') {
          // 数字：直接使用数字值
          const numValue = parseFloat(item.value)
          if (isNaN(numValue)) {
            return null // 数字值无效，返回null
          }
          output.push(numValue)
        } else if (item.type === 'operator') {
          // 运算符：处理运算符优先级
          while (
            operators.length > 0 &&
            operators[operators.length - 1] !== '(' &&
            precedence[operators[operators.length - 1]] >= precedence[item.value]
          ) {
            output.push(operators.pop())
          }
          operators.push(item.value)
        } else if (item.type === 'bracket') {
          if (item.value === '(') {
            operators.push('(')
          } else if (item.value === ')') {
            // 右括号：弹出直到左括号
            while (operators.length > 0 && operators[operators.length - 1] !== '(') {
              output.push(operators.pop())
            }
            if (operators.length > 0 && operators[operators.length - 1] === '(') {
              operators.pop() // 移除左括号
            }
          }
        }
      }

      // 将剩余的运算符加入输出
      while (operators.length > 0) {
        const op = operators.pop()
        if (op === '(' || op === ')') {
          return null // 括号不匹配
        }
        output.push(op)
      }

      return output
    },
    // 计算后缀表达式
    evaluatePostfix(postfix) {
      if (!postfix || postfix.length === 0 || postfix === null) {
        return null
      }

      const stack = []

      for (let i = 0; i < postfix.length; i++) {
        const token = postfix[i]

        if (typeof token === 'number') {
          // 数字：入栈
          stack.push(token)
        } else if (typeof token === 'string' && ['+', '-', '*', '/'].includes(token)) {
          // 运算符：弹出两个操作数，计算结果，入栈
          if (stack.length < 2) {
            return null // 操作数不足
          }
          const b = stack.pop()
          const a = stack.pop()
          let result = null

          switch (token) {
                case '+':
              result = a + b
                  break
                case '-':
              result = a - b
                  break
                case '*':
              result = a * b
                  break
                case '/':
              if (b === 0) {
                return null // 除零错误
              }
              result = a / b
                  break
                default:
              return null
          }

          stack.push(result)
        }
      }

      if (stack.length !== 1) {
        return null // 表达式无效
      }

      return stack[0]
    },
    // 从数据中获取参数值
    getParamValueFromData(paramName, xValue, xAxisDataMap, hasDuplicateXValues = false) {
      if (!xAxisDataMap || !xAxisDataMap.has(xValue)) {
        return null
      }

      const dataItem = xAxisDataMap.get(xValue)
      if (!dataItem || !dataItem.parameters) {
        return null
      }

      // 在参数列表中查找所有匹配的parameterName
      const matchedParams = dataItem.parameters.filter((p) => p.parameterName === paramName)

      if (!matchedParams || matchedParams.length === 0) {
        return null
      }

      if (hasDuplicateXValues && matchedParams.length > 1) {
        // 如果有重复的X轴值，累加所有匹配的参数值
        let sum = 0
        let hasValidNumber = false
        matchedParams.forEach((param) => {
          if (param.parameterValue !== undefined && param.parameterValue !== null) {
            const numValue = parseFloat(param.parameterValue)
            if (!isNaN(numValue)) {
              sum += numValue
              hasValidNumber = true
            }
          }
        })
        return hasValidNumber ? sum : null
      } else {
        // 没有重复的X轴值或只有一个匹配，使用第一个匹配的参数值
        const matchedParam = matchedParams[0]
        if (
          matchedParam &&
          matchedParam.parameterValue !== undefined &&
          matchedParam.parameterValue !== null
        ) {
          return matchedParam.parameterValue
        }
      }

      return null
    },
    startResize(index, event) {
      event.preventDefault()
      event.stopPropagation()
      this.isResizing = true
      this.resizingChartIndex = index
      this.resizeStartY = event.clientY
      const chart = this.chartList[index]
      this.resizeStartHeight = chart?.chartHeight || 400

      document.addEventListener('mousemove', this.doResize)
      document.addEventListener('mouseup', this.stopResize)
      document.body.style.cursor = 'row-resize'
      document.body.style.userSelect = 'none'
    },
    doResize(event) {
      if (!this.isResizing) return

      const deltaY = event.clientY - this.resizeStartY
      const newHeight = this.resizeStartHeight + deltaY
      const minHeight = 200

      const chart = this.chartList[this.resizingChartIndex]
      if (chart) {
        chart.chartHeight = Math.max(newHeight, minHeight)
        this.$nextTick(() => {
          if (chart.chartInstance) {
            chart.chartInstance.resize()
          }
        })
      }
    },
    stopResize() {
      this.cleanupResizeListeners()
    },
    cleanupResizeListeners() {
      document.removeEventListener('mousemove', this.doResize)
      document.removeEventListener('mouseup', this.stopResize)
      document.body.style.cursor = ''
      document.body.style.userSelect = ''
      this.isResizing = false
      this.resizingChartIndex = -1
    },
    disposeAllCharts() {
      this.chartList.forEach((chart, index) => {
        if (chart.chartInstance) {
          chart.chartInstance.dispose()
          chart.chartInstance = null
        }
        // 清理 resize 事件监听器
        if (chart._resizeHandler) {
          window.removeEventListener('resize', chart._resizeHandler)
          delete chart._resizeHandler
        }
        // 清理容器的 ResizeObserver
        const refName = `chartContainer-${index}`
        const containerRef = this.$refs[refName]
        if (containerRef) {
          const container = Array.isArray(containerRef) ? containerRef[0] : containerRef
          if (container && container._chartResizeObserver) {
            container._chartResizeObserver.disconnect()
            delete container._chartResizeObserver
          }
          if (container && container._resizeObserver) {
            container._resizeObserver.disconnect()
            delete container._resizeObserver
          }
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.apaas-custom-check-data {
  overflow-y: auto;
  height: 100%;
  display: flex;
  flex-direction: column;

  // Tab头部样式
  .tab-header {
    background: white;
    padding: 0 20px;
    border-bottom: 1px solid #ebeef5;
    flex-shrink: 0;

    ::v-deep .el-tabs {
      .el-tabs__header {
        margin: 0;
        border-bottom: none;
      }

      .el-tabs__nav-wrap::after {
        height: 1px;
        background-color: #ebeef5;
      }

      .el-tabs__item {
        height: 48px;
        line-height: 48px;
        font-size: 14px;
        color: #606266;

        &.is-active {
          color: #409eff;
          font-weight: 500;
        }

        &:hover {
          color: #409eff;
        }
      }

      .el-tabs__active-bar {
        background-color: #409eff;
      }
    }
  }

  .tab-content {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
  }
}

.statistics-tab {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;

  .page-search-panel {
    background: white;
    padding: 16px 24px;
    border-bottom: 1px solid #ebeef5;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;

    .search-fields {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 12px;
      width: 100%;
    }

    .search-row {
      display: flex;
      align-items: flex-end;
      gap: 10px;
      width: 100%;
    }

    .search-field,
    .search-actions {
      flex: 1 1 calc((100% - 48px) / 3);
      min-width: 0;
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .search-field {
      .field-label {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
        white-space: nowrap;
        min-width: 64px !important;
        text-align: right;
      }

      .el-input,
      .el-select {
        flex: 1;
      }

      :deep(.el-input__inner),
      :deep(.el-select .el-input__inner) {
        height: 32px;
        line-height: 32px;
      }
    }

    .range-field {
      .range-input-group {
        display: flex;
        align-items: center;
        gap: 8px;
        flex: 1;
      }

      .range-input {
        flex: 1;
      }

      .range-separator {
        color: #606266;
        line-height: 32px;
        font-size: 14px;
      }
    }

    .search-actions {
      justify-content: flex-end;
    }

    :deep(.el-button) {
      padding: 0 16px;
      font-size: 14px;
      border-radius: 4px;
      height: 32px;
      line-height: 32px;
    }
  }

  .favorites-panel {
    background: white;
    padding: 16px 20px;
    border-bottom: 1px solid #ebeef5;
    flex-shrink: 0;

    .header-right {
      display: flex;
      align-items: center;
      gap: 12px;
      flex-shrink: 0;

      .favorites-label {
        font-size: 14px;
        color: #303133;
        white-space: nowrap;
      }

      .favorites-select {
        width: 200px;
      }

      .update-favorite-button {
        background: white;
        border: 1px solid #409eff;
        color: #409eff;
        padding: 8px 16px;
        border-radius: 4px;
        font-size: 14px;

        &:hover {
          background: #ecf5ff;
          border-color: #66b1ff;
          color: #66b1ff;
        }

        &:active {
          background: #409eff;
          color: white;
        }
      }

      .add-favorite-button {
        padding: 8px 16px;
        border-radius: 4px;
        font-size: 14px;
      }
    }
  }

  .check-data-panel {
    padding: 16px 20px;
    margin-bottom: 0;
    border-bottom: 1px solid #cbccce;

    .panel-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;

      .panel-title {
        font-size: 18px;
        font-weight: 500;
        color: #303133;
        margin: 0;
        line-height: 1;
      }

      .header-right {
        display: flex;
        align-items: center;
        gap: 12px;
        flex-shrink: 0;

        .favorites-label {
          font-size: 14px;
          color: #303133;
          white-space: nowrap;
        }

        .favorites-select {
          width: 200px;
        }

        .update-favorite-button {
          background: white;
          border: 1px solid #409eff;
          color: #409eff;
          padding: 8px 16px;
          border-radius: 4px;
          font-size: 14px;

          &:hover {
            background: #ecf5ff;
            border-color: #66b1ff;
            color: #66b1ff;
          }

          &:active {
            background: #409eff;
            color: white;
          }
        }

        .add-favorite-button {
          padding: 8px 16px;
          border-radius: 4px;
          font-size: 14px;
        }
      }
    }
  }

  .chart-management-panel {
    background: transparent;
    margin-top: 16px;
    margin-left: 20px;
    border-radius: 4px;
    display: flex;
    gap: 8px;
    flex-shrink: 0;
    min-height: 56px;
    align-items: center;
  }

  .floating-panel {
    position: fixed;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1000;
    transition: all 0.3s ease;

    .floating-panel-toggle {
      width: 48px;
      height: 48px;
      background: #409eff;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
      transition: all 0.3s ease;
      color: white;
      font-size: 20px;

      &:hover {
        background: #66b1ff;
        box-shadow: 0 6px 16px rgba(64, 158, 255, 0.5);
        transform: scale(1.1);
      }
    }

    .floating-panel-content {
      position: absolute;
      right: 60px;
      top: 50%;
      transform: translateY(-50%);
      background: white;
      border-radius: 8px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
      padding: 12px;
      display: flex;
      flex-direction: column;
      gap: 8px;
      min-width: 120px;
      white-space: nowrap;

      ::v-deep .el-button {
        width: 100%;
        min-width: 120px;
        display: inline-flex;
        align-items: center;
        justify-content: flex-start;
        padding: 10px 16px;
        box-sizing: border-box;
        margin-left: 0 !important;

        i {
          margin-right: 8px;
          width: 16px;
          flex-shrink: 0;
          display: inline-flex;
          align-items: center;
          justify-content: center;
        }
      }
    }

    &.expanded {
      .floating-panel-toggle {
        background: #f56c6c;

        &:hover {
          background: #f78989;
        }
      }
    }
  }
  .empty-chart-area {
    min-height: 2px;
    padding: 0 !important;
    margin: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: transparent !important;
  }
  .chart-area {
    background: white;
    margin: 20px;
    margin-top: 10px;
    min-height: 2px;
    padding: 20px;
    border-radius: 4px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    flex-shrink: 0;

    .chart-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
      padding-bottom: 16px;
      border-bottom: 1px solid #ebeef5;
      position: relative;

      .chart-title-section {
        display: flex;
        align-items: center;
        flex: 1;

        .title-edit-icon {
          margin-left: 8px;
          cursor: pointer;
          color: #909399;
          font-size: 14px;
        }

        .title-input {
          width: 200px;

          ::v-deep .el-input__inner {
            border: none;
            border-bottom: 1px solid #409eff;
            border-radius: 0;
            padding-left: 0;
          }
        }

        .chart-title {
          font-size: 16px;
          font-weight: 500;
          cursor: pointer;
          padding: 4px 8px;

          &:hover {
            color: #409eff;
            background: #f5f7fa;
            border-radius: 4px;
          }
        }
      }

      .chart-header-right {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-shrink: 0;

        .el-button {
          margin-left: 0;
        }

        .download-button {
          display: flex;
          align-items: center;
          gap: 4px;
          cursor: pointer;
          color: #909399;
          padding: 4px 8px;
          border-radius: 4px;
          font-size: 14px;
          transition: all 0.3s;

          &:hover {
            color: #409eff;
            background: #f5f7fa;
          }

          i {
            font-size: 14px;
          }
        }

        .delete-button {
          display: flex;
          align-items: center;
          gap: 4px;
          cursor: pointer;
          color: #909399;
          padding: 4px 8px;
          border-radius: 4px;
          font-size: 14px;
          transition: all 0.3s;

          &:hover {
            color: #f56c6c;
            background: #f5f7fa;
          }

          i {
            font-size: 14px;
          }
        }
      }
    }

    .chart-config {
      display: flex;
      flex-wrap: wrap;
      gap: 16px 24px;
      margin-bottom: 20px;
      padding: 16px;
      background: #f5f7fa;
      border-radius: 4px;
      align-items: center;

      .config-item {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-shrink: 0;

        .config-label {
          font-size: 14px;
          white-space: nowrap;
          min-width: 70px;
          color: #606266;
        }

        ::v-deep .el-select {
          width: 150px;
          height: 32px;
        }
        ::v-deep .y-axis-param-select {
          width: 250px !important;

          .el-input__inner {
            height: 32px;
          }

          /* 确保多选模式下筛选输入框可见 */
          .el-select__input {
            display: inline-block !important;
            visibility: visible !important;
            opacity: 1 !important;
          }

          /* 多选标签区域 */
          .el-select__tags {
            max-height: none;
          }

          /* 标签文本省略号 */
          .el-tag {
            max-width: 160px;
            box-sizing: border-box;
            
            .el-select__tags-text {
              max-width: 100%;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
              display: inline-block;
              vertical-align: top;
            }
          }
          
          // 折叠标签时的样式
          .el-select__tags-text {
            max-width: 200px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            display: inline-block;
            vertical-align: top;
          }
        }
        ::v-deep .el-select .el-input__inner {
          height: 32px;
        }
        ::v-deep .el-button {
          margin-left: 0;
        }

        .y-axis-range-input {
          width: 100px;
        }

        .range-separator {
          margin: 0 8px;
          color: #606266;
        }
      }

      .canshu {
        width: 370px;
        ::v-deep .y-axis-param-select {
          width: 280px !important;

          .el-input__inner {
            height: 32px;
          }

          /* 确保多选模式下筛选输入框可见 */
          .el-select__input {
            display: inline-block !important;
            visibility: visible !important;
            opacity: 1 !important;
          }

          /* 多选标签区域 */
          .el-select__tags {
            max-height: none;
          }
        }
      }
    }

    .chart-wrapper {
      position: relative;

      .chart-resize-handle {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 8px;
        cursor: row-resize;
        z-index: 5;
        background: transparent;
        transition: background 0.2s;

        &:hover {
          background: rgba(64, 158, 255, 0.2);
        }

        &::before {
          content: '';
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          width: 40px;
          height: 4px;
          background: #dcdfe6;
          border-radius: 2px;
          transition: background 0.2s;
        }

        &:hover::before {
          background: #409eff;
        }
      }
    }

    .chart-container {
      width: 100%;
      min-height: 200px;
    }
  }

  .formula-dialog-content {
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;

    .selected-params-display {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      padding: 8px;
      background: #f5f7fa;
      border-radius: 4px;
      min-height: 32px;
      align-items: center;

      .selected-param-tag {
        display: inline-flex;
        align-items: center;
        padding: 2px 8px;
        background: #e8f5e9;
        border: 1px solid #67c23a;
        border-radius: 3px;
        font-size: 12px;
        color: #67c23a;
        line-height: 1.5;
      }
    }

    .formula-builder {
      display: flex;
      flex-direction: column;
      gap: 12px;
      position: relative;
      padding-top: 30px; // 为帮助按钮留出空间

      .builder-help {
        position: absolute;
        top: 0;
        right: 0;
        z-index: 10;

        .help-button {
          color: #409eff;
          font-size: 12px;
          padding: 4px 8px;
          border: none;
          background: transparent;

          &:hover {
            color: #66b1ff;
          }

          i {
            margin-right: 4px;
          }
        }
      }
    }

    .draggable-items {
      display: flex;
      gap: 12px;
      padding: 12px;
      background: #f5f7fa;
      border-radius: 4px;
      border: 1px solid #dcdfe6;
      flex-wrap: wrap;
    }

    .items-section {
      flex: 1;
      min-width: 150px;
      display: flex;
      flex-direction: column;
      gap: 6px;

      .section-title {
        font-size: 12px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 4px;
        display: flex;
        align-items: center;
        gap: 4px;

        .section-tip {
          font-size: 10px;
          font-weight: normal;
          color: #909399;
        }
      }

      .items-container {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        align-items: flex-start;
      }

      .empty-tip {
        font-size: 12px;
        color: #909399;
        padding: 4px 0;
      }

      .number-section-container {
        display: flex;
        flex-direction: column;
        gap: 8px;
        width: 100%;
      }

      .number-input-row {
        display: flex;
        align-items: center;
        gap: 8px;
        width: 100%;

        .number-label {
          font-size: 12px;
          font-weight: 600;
          color: #303133;
          white-space: nowrap;
        }

        ::v-deep .el-input-number {
          flex: 0 0 auto;
        }

        ::v-deep .el-button {
          flex: 0 0 auto;
        }
      }

      .recent-numbers {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin-top: 0;
      }
    }

    .draggable-item {
      padding: 4px 8px;
      background: white;
      border: 1px solid #dcdfe6;
      border-radius: 3px;
      cursor: move;
      user-select: none;
      font-size: 12px;
      color: #303133;
      transition: all 0.2s;
      line-height: 1.5;

      &:hover {
        background: #ecf5ff;
        border-color: #409eff;
        color: #409eff;
        transform: translateY(-1px);
        box-shadow: 0 1px 4px rgba(64, 158, 255, 0.2);
      }

      &.param-item {
        background: #e8f5e9;
        border-color: #67c23a;
        color: #67c23a;
        font-size: 11px;

        &:hover {
          background: #c8e6c9;
          border-color: #67c23a;
        }
      }

      &.operator-item {
        background: #fff3e0;
        border-color: #e6a23c;
        color: #e6a23c;
        font-weight: 600;

        &:hover {
          background: #ffe0b2;
          border-color: #e6a23c;
        }
      }

      &.bracket-item {
        background: #f3e5f5;
        border-color: #9c27b0;
        color: #9c27b0;
        font-weight: 600;
      font-size: 14px;
        padding: 4px 10px;

        &:hover {
          background: #e1bee7;
          border-color: #9c27b0;
        }
      }

      &.number-item {
        background: #e3f2fd;
        border-color: #2196f3;
        color: #2196f3;

        &:hover {
          background: #bbdefb;
          border-color: #2196f3;
        }
      }
    }

    .formula-preview-area {
      display: flex;
      flex-direction: column;
      gap: 8px;

      .preview-title {
        font-size: 12px;
        font-weight: 600;
      color: #303133;
      }

      .preview-container {
        min-height: 60px;
        padding: 10px;
        background: #f5f7fa;
        border: 2px dashed #dcdfe6;
        border-radius: 4px;
      display: flex;
        flex-wrap: wrap;
        gap: 6px;
        align-items: flex-start;
        align-content: flex-start;

        &.drag-over {
          border-color: #409eff;
          background: #ecf5ff;
        }
      }

      .empty-preview {
        width: 100%;
        text-align: center;
        color: #909399;
        font-size: 12px;
        padding: 15px 0;
      }

      .preview-item {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 4px 8px;
        background: white;
        border: 1px solid #dcdfe6;
        border-radius: 3px;
        font-size: 12px;
        position: relative;
        line-height: 1.5;
        cursor: move;
        user-select: none;
        transition: all 0.2s;

        &:hover {
          box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
          transform: translateY(-1px);
        }

        &.is-dragging {
          opacity: 0.5;
          transform: scale(0.95);
        }

        &.drag-over {
          border-color: #409eff;
          border-width: 2px;
          box-shadow: 0 0 8px rgba(64, 158, 255, 0.4);
        }

        &.is-param {
          background: #e8f5e9;
          border-color: #67c23a;
          color: #67c23a;
          font-size: 11px;
        }

        &.is-operator {
          background: #fff3e0;
          border-color: #e6a23c;
          color: #e6a23c;
          font-weight: 600;
        }

        &.is-bracket {
          background: #f3e5f5;
          border-color: #9c27b0;
          color: #9c27b0;
          font-weight: 600;
          font-size: 14px;
          padding: 4px 10px;
        }

        &.is-number {
          background: #e3f2fd;
          border-color: #2196f3;
          color: #2196f3;
        }

        .item-content {
          line-height: 1.5;
        }

        .remove-btn {
          cursor: pointer;
          color: #909399;
          font-size: 10px;
          padding: 1px;
          border-radius: 50%;
          transition: all 0.2s;
          margin-left: 2px;

          &:hover {
            color: #f56c6c;
            background: #fef0f0;
          }
        }
      }

      .preview-actions {
        display: flex;
        gap: 6px;
        justify-content: flex-end;

        ::v-deep .el-button {
          padding: 6px 12px;
          font-size: 12px;
        }
      }
    }
  }
}
::v-deep .el-tag--light{
  margin-right: 5px !important;
}
.search-field{
  flex: 1 1 calc((100% - 30px) / 4) !important;
  max-width: calc(25% - 15px) !important;
  ::v-deep .el-select {
    .el-tag {
      max-width: 70px;
      font-size: 12px !important;
      color: #909399 !important;
      background: #ecedee !important;
      box-sizing: border-box;
      
      .el-select__tags-text {
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        display: inline-block;
        vertical-align: top;
      }
    }
    
    // 折叠标签时的样式
    .el-select__tags-text {
      max-width: 60px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      display: inline-block;
      vertical-align: top;
    }
  }
}
.chart-config{
  ::v-deep .el-select {
    .el-tag {
      max-width: 160px;
      box-sizing: border-box;
      
      .el-select__tags-text {
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        display: inline-block;
        vertical-align: top;
      }
    }
    
    // 折叠标签时的样式
    .el-select__tags-text {
      max-width: 160px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      display: inline-block;
      vertical-align: top;
    }
  }
}
</style>

<style lang="scss" scoped>
.formula-dialog {
  ::v-deep .el-dialog {
    height: 70vh;
    display: flex;
    flex-direction: column;
  }

  ::v-deep .el-dialog__header {
    flex-shrink: 0;
    padding: 20px 20px 10px;
  }

  ::v-deep .el-dialog__body {
    position: relative;
    flex: 1;
    overflow: hidden;
    padding: 20px;
  }

  ::v-deep .el-dialog__footer {
    flex-shrink: 0;
    padding: 10px 20px 20px;
    border-top: 1px solid #ebeef5;
  }
}
::v-deep .el-button {
  line-height: 0.85 !important;
}
/* 帮助弹窗样式（全局） */
::v-deep .formula-help-popover {
  .help-content {
    p {
      margin: 0;
      font-size: 14px;
      line-height: 1.6;
      color: #303133;
    }
  }
}
/* 机型选择穿梭框样式（全局，确保 append-to-body 时也生效） */
::v-deep .model-select-dialog {
  padding: 20px 0;

  .transfer-item {
    display: flex;
    align-items: center;

    .transfer-item-label {
      font-size: 14px;
      color: #303133;
    }
  }

  .el-transfer-panel__header {
    .el-input {
      width: 260px;

      .el-input__inner {
        width: 260px;
      }
    }
  }
  .el-transfer-panel__body {
    height: 300px;
  }
  .el-transfer-panel__list {
    height: 230px;
    overflow-y: auto;
    padding: 0 10px;
  }
  .el-transfer__buttons {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0 20px;

    .el-button {
      margin: 0;
      margin-bottom: 10px;

      &:last-child {
        margin-bottom: 0;
      }
    }
  }
}
::v-deep .el-transfer {
  display: flex;
  justify-content: space-between;
}
::v-deep .el-transfer-panel {
  width: 300px !important;
  .el-input {
    width: 260px !important;
  }
}
</style>
