<template>
  <div class="model-query-tab tab-content">
    <!-- 顶部操作栏 -->
    <div class="page-search-panel check-data-panel">
      <div class="panel-header">
        <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" @click="handleAddFavorite">新增常用</el-button>
          <el-button class="hidden-params-button" @click="handleShowHiddenParams">
            已隐藏参数
            <span v-if="hiddenParams.length > 0" class="hidden-count">({{ hiddenParams.length }})</span>
            </el-button>
            <el-button class="download-comparison-data-button" @click="handleDownloadComparisonData">
              下载对比数据
            </el-button>
        </div>
      </div>
    </div>

    <!-- 主体内容：左侧参数树 + 右侧对比表格 -->
    <div class="model-query-content">
      <!-- 左侧参数选择区域 -->
      <div class="left-param-panel">
        <div class="tree-search-header">
          <el-radio-group v-model="treeSearchMode" size="mini" class="search-mode-switch">
            <el-radio-button label="subsystem">子系统</el-radio-button>
            <el-radio-button label="parts">零部件名称</el-radio-button>
          </el-radio-group>
        </div>
        <el-input
          v-model="treeFilterText"
          size="small"
          :placeholder="treeSearchMode === 'subsystem' ? '请输入子系统名称' : '请输入零部件名称'"
          clearable
          class="tree-search"
        ></el-input>
        <el-tree
          ref="paramTree"
          :data="treeData"
          node-key="id"
          show-checkbox
          :checked-keys="checkedKeys"
          :default-expanded-keys="[]"
          :props="{ children: 'children', label: 'label' }"
          :filter-node-method="filterTreeNode"
          @check="handleTreeCheck"
        >
          <span slot-scope="{ data }" class="custom-tree-node">
            <span>{{ data.label }}</span>
            <span v-if="data.tip" class="red-tip">{{ data.tip }}</span>
          </span>
        </el-tree>
      </div>

      <!-- 右侧机型对比表格 -->
      <div class="right-comparison-panel">
        <div class="comparison-table-wrapper">
          <table class="comparison-table">
            <thead>
              <tr>
                <th class="param-column">参数名称</th>
                <th
                  v-for="(model, index) in comparisonModels"
                  :key="index"
                  class="model-column"
                >
                  <div class="model-header">
                    <div v-if="model.name" class="model-name">{{ model.name }}</div>
                    <i
                      v-if="model.name"
                      class="el-icon-close model-remove"
                      @click="handleRemoveModel(index)"
                    ></i>
                    <div v-else class="add-model-placeholder" @click="handleAddModel">
                      <i class="el-icon-plus"></i>
                      <span>添加机型</span>
                    </div>
                  </div>
                </th>
                <th class="add-column">
                  <div class="add-model-placeholder" @click="handleAddModel">
                    <i class="el-icon-plus"></i>
                    <span>添加机型</span>
                  </div>
                </th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(param, paramIndex) in displayParams" :key="paramIndex">
                <td class="param-column">
                  <span class="param-name">{{ getParamDisplayName(param) }}</span>
                  <i
                    class="el-icon-remove-outline param-config-icon"
                    @click.stop="handleHideParam(param)"
                  ></i>
                </td>
                <td
                  v-for="(model, modelIndex) in comparisonModels"
                  :key="modelIndex"
                  class="model-column"
                >
                  {{ getParamValue(model, param) }}
                </td>
                <td class="add-column"></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>

    <!-- 添加机型弹窗 -->
    <el-dialog
      title="选择机型"
      :visible.sync="addModelDialogVisible"
      width="800px"
      append-to-body
      @close="handleAddModelDialogClose"
    >
      <div class="model-select-dialog">
        <el-input
          v-model="modelSearchText"
          placeholder="请输入产品型号，状态代号/产品编号，平台，系列搜索"
          prefix-icon="el-icon-search"
          clearable
          class="model-search-input"
        ></el-input>
        <div class="model-list-wrapper">
          <el-table
            ref="modelTable"
            :data="filteredModelList"
            height="400"
            @selection-change="handleModelSelectionChange"
          >
            <el-table-column type="selection" width="55" />
            <el-table-column prop="modelName" label="产品型号" min-width="150" />
            <el-table-column prop="productNumber" label="状态代号/产品编号" min-width="100" />
            <el-table-column prop="platform" label="平台" min-width="100" />
            <el-table-column prop="series" label="系列" min-width="100" />
          </el-table>
        </div>
      </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="已隐藏参数"
      :visible.sync="hiddenParamsDialogVisible"
      width="800px"
      append-to-body
      @close="handleHiddenParamsDialogClose"
    >
      <div class="hidden-params-dialog-content">
        <div v-if="hiddenParamsList.length === 0" class="empty-hint">
          暂无隐藏的参数
        </div>
        <template v-else>
          <div class="hidden-params-header">
            <el-button size="small" @click="handleRestoreAll">
              全部恢复
            </el-button>
            <el-button size="small" :disabled="selectedParamsToRestore.length === 0" @click="handleRestoreSelected">
              恢复已选择
            </el-button>
          </div>
          <el-table
            ref="hiddenParamsTable"
            :data="hiddenParamsList"
            border
            height="400"
            style="width: 100%"
            @selection-change="handleHiddenParamsSelectionChange"
          >
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column prop="subsystemName" label="子系统" min-width="150" />
            <el-table-column prop="parameterName" label="参数名称" min-width="200" show-overflow-tooltip />
          </el-table>
        </template>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="handleHiddenParamsDialogClose">取消</el-button>
        <el-button
          type="primary"
          :disabled="selectedParamsToRestore.length === 0"
          @click="handleConfirmRestoreParams"
        >
          确定恢复({{ selectedParamsToRestore.length }})
        </el-button>
      </div>
    </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>
</template>

<script>
import api from '@/api'
import { getUserId } from '@/utils'

export default {
  name: 'ModelQuery',
  data() {
    return {
      favoritesValue: '',
      favoritesOptions: [], // 常用列表，从接口获取
      currentCommonConfig: null, // 当前选中的常用配置
      allTreeData: [], // 完整的树数据（未过滤）
      allNodeMap: {}, // 完整的节点映射（未过滤）
      treeFilterText: '',
      treeSearchMode: 'subsystem', // 搜索模式：'subsystem' 搜索子系统，'parts' 搜索零部件名称
      checkedKeys: [],
      defaultExpandedKeys: [],
      treeData: [],
      // 树节点映射：id -> { label, parentLabel, isParent }
      nodeMap: {},
      comparisonModels: [],
      loadingModels: false,
      // 添加机型弹窗相关
      addModelDialogVisible: false,
      modelList: [], // 所有机型列表（用于弹窗选择）
      selectedModels: [], // 弹窗中选中的机型
      modelSearchText: '', // 机型搜索文本
      loadingModelDetail: false, // 加载机型详情中
      // 所有机型的详情数据，格式：{ modelId: { "子系统名称": [{ parameterName, parameterType, minorVersion, ... }] } }
      allModelDetailData: {},
      // 隐藏的参数列表，存储参数的唯一标识：`${subsystemName}-${parameterType}-${parameterName}`
      hiddenParams: [],
      hiddenParamsDialogVisible: false, // 已隐藏参数弹窗显示状态
      selectedParamsToRestore: [], // 临时选中的要恢复的参数keys
      // 新增常用弹窗相关
      addFavoriteDialogVisible: false,
      addFavoriteFormData: {
        commonName: ''
      },
      addFavoriteFormRules: {
        commonName: [
          { required: true, message: '请输入常用名称', trigger: 'blur' },
          { max: 50, message: '常用名称不能超过50个字符', trigger: 'blur' }
        ]
      },
      savingFavorite: false, // 保存常用中
      // 所有参数数据（从 GET_ALL_DATA_SYSTEAM_LIST 获取）
      allParametersData: {}, // 格式：{ "子系统名称": [{ parameterName, parameterId, ... }] }
      // 保存完整的参数数据（不受常用配置影响，用于树节点选中时展示）
      savedAllParametersData: {}, // 格式：{ "子系统名称": [{ parameterName, parameterId, ... }] }
      // 是否使用常用配置过滤（当选中常用时为 true，当用户再次选中树节点时为 false）
      useCommonFilter: false
    }
  },
  computed: {
    displayParams() {
      // 根据选中的树节点和 GET_ALL_DATA_SYSTEAM_LIST 返回的所有参数数据，生成参数列表
      const paramMap = new Map() // 用于去重，key: `${subsystemName}-${parameterName}`，value: { parameterName, subsystemName, parameterId, parameterType }

      // 获取选中的子系统名称和零部件名称（参数类型）
      const { subsystemNames, parameterTypes, subsystemTypes } = this.getSelectedSubsystemsAndTypes()

      // 如果没有选中任何节点，返回空数组
      if (subsystemNames.length === 0) {
        return []
      }

      // 从 allParametersData 中获取参数列表（根据子系统和参数名称）
      Object.keys(this.allParametersData).forEach(subsystemName => {
        // 检查该子系统是否在选中的列表中
        const isSubsystemSelected = subsystemNames.includes(subsystemName)
        if (!isSubsystemSelected) {
          return
        }

        const paramList = this.allParametersData[subsystemName]
        if (!Array.isArray(paramList)) {
          return
        }

        // 遍历该子系统下的所有参数
        paramList.forEach(item => {
          const parameterName = item.parameterName || ''
          const parameterId = item.parameterId || ''
          const partsName = item.partsName || ''
          const subsystem = item.subsystem || subsystemName

          if (parameterName) {
            // 确定用于匹配和显示的零部件名称（partsName）
            // 如果 partsName 是 `/`，则使用 subsystem 作为显示名称
            const displayPartsName = partsName === '/' ? subsystem : partsName

            // 检查是否匹配选中的零部件名称
            // 如果选中了父节点（子系统），则显示该子系统下的所有参数
            // 如果选中了子节点（零部件），则只显示匹配的零部件参数
            let shouldInclude = false
            if (parameterTypes.length === 0) {
              // 如果只选中了父节点（子系统），显示该子系统下的所有参数
              shouldInclude = true
            } else {
              // 如果选中了子节点（零部件），检查是否匹配
              // 检查是否在 parameterTypes 中，或者是否在 subsystemTypes 中（格式：子系统名称-零部件名称）
              shouldInclude = parameterTypes.includes(displayPartsName) ||
                subsystemTypes.includes(`${subsystemName}-${displayPartsName}`)
            }

            if (shouldInclude) {
              // 使用 subsystemName 和 parameterName 作为唯一标识
              const key = `${subsystemName}-${parameterName}`
              if (!paramMap.has(key)) {
                paramMap.set(key, {
                  parameterName: parameterName,
                  subsystemName: subsystemName,
                  parameterId: parameterId,
                  partsName: partsName, // 保存原始的 partsName
                  displayPartsName: displayPartsName // 保存用于显示的零部件名称（如果是 `/` 则使用 subsystem）
                })
              }
            }
          }
        })
      })

      // 转换为数组并排序（按子系统名称和参数名称），然后过滤掉隐藏的参数和不在常用配置中的参数
      const allParams = Array.from(paramMap.values()).sort((a, b) => {
        if (a.subsystemName !== b.subsystemName) {
          return a.subsystemName.localeCompare(b.subsystemName)
        }
        return a.parameterName.localeCompare(b.parameterName)
      })

      // 过滤：1. 手动隐藏的参数 2. 不在常用配置中的参数（如果已选择常用且树节点选中）
      return allParams.filter(param => {
        // 过滤手动隐藏的参数（使用新的key格式：subsystemName-parameterName）
        const key = `${param.subsystemName}-${param.parameterName}`
        if (this.hiddenParams.includes(key)) {
          return false
        }

        // 如果已选择常用配置，需要检查参数是否在常用中
        // 注意：这里 param 已经在 allParams 中，说明它已经通过了树节点选中状态的过滤
        // 所以如果参数不在常用中，即使树节点选中也不显示
        if (this.currentCommonConfig && this.currentCommonConfig.subsystems) {
          // 查找该参数是否在常用配置中（支持精确匹配和包含匹配）
          const subsystemConfig = this.currentCommonConfig.subsystems.find(s => {
            return s.subsystem === param.subsystemName ||
                   s.subsystem.includes(param.subsystemName) ||
                   param.subsystemName.includes(s.subsystem)
          })
          if (!subsystemConfig) {
            // 如果该子系统不在常用配置中，不显示该参数（即使树节点选中）
            return false
          }

          // 检查 parameterId 或 parameterName 是否在常用配置的 parameters 中
          // 优先使用 parameterId 匹配，其次使用 parameterName 匹配
          if (param.parameterId) {
            const isInCommon = subsystemConfig.parameters.some(
              p => p.parameterId === param.parameterId
            )
            if (!isInCommon) {
              // 参数不在常用中，即使树节点选中也不显示
              return false
            }
          } else {
            // 如果找不到 parameterId，使用 parameterName 匹配（支持精确匹配和包含匹配）
            const isInCommon = subsystemConfig.parameters.some(p => {
              return p.parameterName === param.parameterName ||
                     (p.parameterName && param.parameterName &&
                      (p.parameterName.includes(param.parameterName) ||
                       param.parameterName.includes(p.parameterName)))
            })
            if (!isInCommon) {
              // 参数不在常用中，即使树节点选中也不显示
              return false
            }
          }
        }

        return true
      })
    },
    // 已隐藏参数列表（用于弹窗显示）
    hiddenParamsList() {
      // 从 allParametersData 中查找隐藏的参数信息
      const hiddenList = []
      const hiddenKeysSet = new Set(this.hiddenParams)

      // 遍历所有参数数据，收集隐藏的参数信息
      Object.keys(this.allParametersData).forEach(subsystemName => {
        const paramList = this.allParametersData[subsystemName]
        if (!Array.isArray(paramList)) {
          return
        }

        paramList.forEach(item => {
          const parameterName = item.parameterName || ''
          const key = `${subsystemName}-${parameterName}`

          // 如果该参数在隐藏列表中，且还没有添加到 hiddenList
          if (hiddenKeysSet.has(key)) {
            const exists = hiddenList.some(p => p.key === key)
            if (!exists) {
              hiddenList.push({
                subsystemName: subsystemName,
                parameterName: parameterName,
                key: key
              })
            }
          }
        })
      })

      // 排序（按子系统名称和参数名称）
      return hiddenList.sort((a, b) => {
        if (a.subsystemName !== b.subsystemName) {
          return a.subsystemName.localeCompare(b.subsystemName)
        }
        return a.parameterName.localeCompare(b.parameterName)
      })
    },
    // 过滤机型列表（排除已添加的机型，并根据搜索文本过滤）
    filteredModelList() {
      const addedModelIds = new Set(this.comparisonModels.map(m => m.id))
      let filtered = this.modelList.filter(model => {
        const modelId = model.id || model.rowId || model.engineModelID
        return !addedModelIds.has(modelId)
      })

      // 根据搜索文本过滤（支持 modelName、productNumber、platform、series 四个字段）
      if (this.modelSearchText) {
        const searchText = this.modelSearchText.toLowerCase()
        filtered = filtered.filter(model => {
          const modelName = (model.modelName || model.productFullName || '').toLowerCase()
          const productNumber = (model.productNumber || '').toLowerCase()
          const platform = (model.platform || '').toLowerCase()
          const series = (model.series || '').toLowerCase()
          // 只要任一字段包含搜索关键字，就显示该机型
          return modelName.includes(searchText) ||
                 productNumber.includes(searchText) ||
                 platform.includes(searchText) ||
                 series.includes(searchText)
        })
      }

      return filtered
    }
  },
  watch: {
    treeFilterText(val) {
      if (this.$refs.paramTree) {
        this.$refs.paramTree.filter(val)
      }
    },
    treeSearchMode() {
      // 切换搜索模式时，重新应用当前搜索文本
      if (this.$refs.paramTree && this.treeFilterText) {
        this.$refs.paramTree.filter(this.treeFilterText)
      }
    }
  },
  mounted() {
    // 加载树数据（参数完成后会自动调用 loadFavoritesList）
    this.loadTreeData()
  },
  methods: {
    filterTreeNode(value, data) {
      if (!value) return true
      const searchValue = value.toLowerCase()
      const nodeInfo = this.nodeMap[data.id]
      if (!nodeInfo) {
        // 如果没有节点信息，使用默认过滤逻辑
        return (data.label || '').toLowerCase().includes(searchValue)
      }
      const nodeLabel = (data.label || '').toLowerCase()
      // 判断节点级别：一级节点（parentLabel === null），二级节点（parentLabel !== null）
      const isFirstLevel = nodeInfo.parentLabel === null
      const isSecondLevel = nodeInfo.parentLabel !== null

      if (this.treeSearchMode === 'subsystem') {
        // 搜索子系统：只针对一级节点（子系统）
        if (isFirstLevel) {
          // 一级节点（子系统）：检查是否匹配
          return nodeLabel.includes(searchValue)
        } else if (isSecondLevel) {
          // 二级节点（零部件名称）：如果父节点（一级节点）匹配，则显示
          const parentLabel = (nodeInfo.parentLabel || '').toLowerCase()
          return parentLabel.includes(searchValue)
        }
        return false
      } else {
        // 搜索零部件名称：只针对二级节点（零部件名称）
        if (isSecondLevel) {
          // 二级节点（零部件名称）：检查是否匹配
          return nodeLabel.includes(searchValue)
        } else if (isFirstLevel) {
          // 一级节点（子系统）：如果其下任何二级子节点匹配，则显示
          if (data.children && Array.isArray(data.children)) {
            return data.children.some((child) => {
              const childLabel = (child.label || '').toLowerCase()
              return childLabel.includes(searchValue)
            })
          }
        }
        return false
      }
    },
    handleTreeCheck(data, checkedInfo) {
      // 更新选中的keys
      // 注意：当树节点选中/取消选中时，displayParams 会自动更新
      // 如果树节点未选中，参数不显示（可以通过选中树节点恢复）
      // 如果树节点选中但参数不在常用中，参数不显示（即使选中树节点也不显示）
      this.checkedKeys = checkedInfo.checkedKeys
      // 如果有已添加的机型，根据新选中的树节点重新加载参数数据
      this.reloadModelDetailsForCheckedNodes()
    },
    getParamValue(model, param) {
      // param 是 { parameterName, subsystemName, parameterId }
      if (!model || !model.id || !param) {
        return '-'
      }

      const modelData = this.allModelDetailData[model.id]
      if (!modelData || typeof modelData !== 'object') {
        return '-'
      }

      // 查找对应子系统的数据
      const subsystemData = modelData[param.subsystemName]
      if (!Array.isArray(subsystemData)) {
        return '-'
      }

      // 查找匹配的参数：根据 subsystemName 和 parameterName 匹配
      // 优先使用 parameterId 匹配，其次使用 parameterName 匹配
      let matchedParam = null
      if (param.parameterId) {
        matchedParam = subsystemData.find(item => {
          return item.subsystemName === param.subsystemName &&
            item.parameterId === param.parameterId
        })
      }
      if (!matchedParam) {
        matchedParam = subsystemData.find(item => {
          return item.subsystemName === param.subsystemName &&
            item.parameterName === param.parameterName
        })
      }

      if (matchedParam) {
        // 只返回 parameterValue
        if (matchedParam.parameterValue !== undefined && matchedParam.parameterValue !== null && matchedParam.parameterValue !== '') {
          return matchedParam.parameterValue
        }
      }

      return '-'
    },
    // 获取参数的显示名称（用于第一列显示）
    getParamDisplayName(param) {
      if (!param) {
        return ''
      }
      // 只显示参数名称，不显示零部件名称
      return param.parameterName || ''
    },
    handleAddModel() {
      // 打开弹窗
      this.addModelDialogVisible = true
      // 如果机型列表为空，加载机型列表
      if (this.modelList.length === 0) {
        this.loadModelListForDialog()
      }
    },
    // 加载弹窗中的机型列表
    loadModelListForDialog() {
      const request = {
        ...api.GET_ENGINE_LIST_SELF,
        params: {
          page: 1,
          size: 999
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          if (resp && resp.data && resp.data.list) {
            this.modelList = resp.data.list
          } else {
            this.modelList = []
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取机型列表失败:', err)
          this.$message.error('获取机型列表失败')
          this.modelList = []
        })
    },
    // 机型选择变化
    handleModelSelectionChange(selection) {
      this.selectedModels = selection
    },
    // 关闭添加机型弹窗
    handleAddModelDialogClose() {
      this.addModelDialogVisible = false
      this.selectedModels = []
      this.modelSearchText = ''
      // 清空表格选择
      if (this.$refs.modelTable) {
        this.$refs.modelTable.clearSelection()
      }
    },
    // 确认添加机型
    handleConfirmAddModel() {
      if (this.selectedModels.length === 0) {
        this.$message({
          type: 'warning',
          message: '请至少选择一个机型'
        })
        return
      }

      // 检查是否有选中的树节点
      const { subsystemNames, parameterTypes, subsystemTypes } = this.getSelectedSubsystemsAndTypes()
      if (subsystemNames.length === 0 && parameterTypes.length === 0) {
        this.$message({
          type: 'warning',
          message: '请先在左侧选择参数节点'
        })
        return
      }

      this.loadingModelDetail = true
      // 批量加载选中机型的详情
      const loadPromises = this.selectedModels.map(model => {
        const modelId = model.id || model.rowId || model.engineModelID
        return this.loadModelDetail(modelId, model, subsystemTypes)
      })

      Promise.all(loadPromises)
        .then(() => {
          // this.$message.success('添加机型成功')
          this.handleAddModelDialogClose()
        })
        .catch((err) => {
          console.error('加载机型详情失败:', err)
          this.$message.error('加载机型详情失败')
        })
        .finally(() => {
          this.loadingModelDetail = false
        })
    },
    // 加载单个机型详情
    loadModelDetail(modelId, modelData, subsystemTypes) {
      return new Promise((resolve, reject) => {
        const request = {
          ...api.GET_MODEL_QUERY,
          params: {
            engineModelID: modelId,
            userID: getUserId(),
            subsystemParts: subsystemTypes // 格式：["子系统名称-参数类型"]
          },
          disableSuccessMsg: true
        }

        this.$request(request)
          .asyncThen((resp) => {
            if (resp && resp.data) {
              // 保存机型的详情数据，格式：{ "子系统名称": [{ parameterName, parameterType, minorVersion, ... }] }
              // 为每个参数项添加 subsystemName（如果还没有）
              const processedData = {}
              Object.keys(resp.data).forEach(subsystemName => {
                const paramList = resp.data[subsystemName]
                if (Array.isArray(paramList)) {
                  processedData[subsystemName] = paramList.map(item => ({
                    ...item,
                    subsystemName: item.subsystemName || subsystemName
                  }))
                }
              })

              // 保存到 allModelDetailData（合并数据，而不是覆盖）
              const existingData = this.allModelDetailData[modelId] || {}
              // 合并新旧数据，新数据覆盖旧数据
              const mergedData = { ...existingData, ...processedData }
              this.$set(this.allModelDetailData, modelId, mergedData)

              // 如果已选择常用配置，自动隐藏不在范围内的参数
              if (this.currentCommonConfig) {
                // 不再调用 hideParamsNotInCommon，让 displayParams 自动过滤
              }

              // 检查机型是否已存在，如果不存在才添加
              const existingModel = this.comparisonModels.find(m => m.id === modelId)
              if (!existingModel) {
                // 将机型添加到对比列表
                const newModel = {
                  id: modelId,
                  name: modelData.modelName || modelData.productFullName || '未知机型',
                  image: modelData.image || modelData.imageUrl || ''
                }
                this.comparisonModels.push(newModel)
              }
              resolve()
            } else {
              // 即使没有数据，也保存空数据（参数为空）
              const existingData = this.allModelDetailData[modelId] || {}
              this.$set(this.allModelDetailData, modelId, existingData)

              // 检查机型是否已存在，如果不存在才添加
              const existingModel = this.comparisonModels.find(m => m.id === modelId)
              if (!existingModel) {
                const newModel = {
                  id: modelId,
                  name: modelData.modelName || modelData.productFullName || '未知机型',
                  image: modelData.image || modelData.imageUrl || ''
                }
                this.comparisonModels.push(newModel)
              }
              resolve()
            }
          })
          .asyncErrorCatch((err) => {
            console.error('获取机型详情失败:', err)
            // 即使失败，也保存空数据（参数为空）
            const existingData = this.allModelDetailData[modelId] || {}
            this.$set(this.allModelDetailData, modelId, existingData)

            // 检查机型是否已存在，如果不存在才添加
            const existingModel = this.comparisonModels.find(m => m.id === modelId)
            if (!existingModel) {
              const newModel = {
                id: modelId,
                name: modelData.modelName || modelData.productFullName || '未知机型',
                image: modelData.image || modelData.imageUrl || ''
              }
              this.comparisonModels.push(newModel)
            }
            reject(err)
          })
      })
    },
    // 根据当前选中的树节点重新加载已添加机型的参数数据
    reloadModelDetailsForCheckedNodes() {
      // 如果没有已添加的机型，直接返回
      if (!this.comparisonModels || this.comparisonModels.length === 0) {
        return
      }

      // 获取当前选中的树节点对应的 subsystemTypes
      const { subsystemNames, parameterTypes, subsystemTypes } = this.getSelectedSubsystemsAndTypes()

      // 如果没有选中任何节点，不加载数据
      if (subsystemNames.length === 0 && parameterTypes.length === 0) {
        return
      }

      // 对于每个已添加的机型，重新加载参数数据
      const loadPromises = this.comparisonModels.map(model => {
        const modelId = model.id
        if (!modelId) {
          return Promise.resolve()
        }

        // 从 modelList 中查找对应的机型数据，如果找不到则使用 model 本身
        let modelData = this.modelList.find(m =>
          (m.id || m.rowId || m.engineModelID) === modelId
        )
        if (!modelData) {
          // 如果 modelList 中找不到，使用 comparisonModels 中的 model 数据
          modelData = {
            id: modelId,
            modelName: model.name,
            productFullName: model.name,
            image: model.image,
            imageUrl: model.image
          }
        }

        // 重新加载该机型的参数数据
        return this.loadModelDetail(modelId, modelData, subsystemTypes)
      })

      // 等待所有机型数据加载完成
      Promise.all(loadPromises)
        .then(() => {
          // 数据加载完成，displayParams 会自动更新
        })
        .catch((err) => {
          console.error('重新加载机型详情失败:', err)
        })
    },
    // 从详情数据中提取参数值（旧方法，保留以备用）
    extractParamsFromDetail(detailData) {
      const params = {}
      if (!detailData || typeof detailData !== 'object') {
        return params
      }

      // 遍历详情数据，提取参数值
      // 详情数据格式: { "子系统名": [{ parameterType: "参数类型", parameterName: "参数名", parameterValue: "值", ... }] }
      Object.keys(detailData).forEach((subsystemName) => {
        const paramList = detailData[subsystemName]
        if (Array.isArray(paramList)) {
          paramList.forEach((item) => {
            const parameterName = item.parameterName || ''
            // 根据参数名称找到对应的 paramMap key
            const paramKey = Object.keys(this.paramMap).find(key => {
              return this.paramMap[key].label === parameterName
            })
            if (paramKey && item.parameterValue !== undefined && item.parameterValue !== null) {
              params[paramKey] = item.parameterValue
            }
          })
        }
      })

      return params
    },
    // 从 list 中提取参数值
    extractParamsFromList(list) {
      const params = {}
      if (!Array.isArray(list) || list.length === 0) {
        return params
      }

      // 遍历 list，提取参数值
      list.forEach((item) => {
        const parameterName = item.parameterName || ''
        // 根据参数名称找到对应的 paramMap key
        const paramKey = Object.keys(this.paramMap).find(key => {
          return this.paramMap[key].label === parameterName
        })
        // 机型列展示的参数值使用 minorVersion
        if (paramKey && item.minorVersion !== undefined && item.minorVersion !== null) {
          params[paramKey] = item.minorVersion
        }
      })

      return params
    },
    // 根据选中的树节点提取父级和子级
    getSelectedSubsystemsAndTypes() {
      const subsystemNames = []
      const parameterTypes = []
      const subsystemTypes = [] // 格式：["子系统名称-参数类型"]
      const processedSubsystems = new Set()
      const processedSubsystemTypes = new Set() // 用于去重
      const subsystemsWithChildren = new Set() // 记录有子节点被选中的子系统

      // 遍历选中的节点
      this.checkedKeys.forEach((nodeId) => {
        const nodeInfo = this.nodeMap[nodeId]
        if (!nodeInfo) return

        if (nodeInfo.isParent) {
          // 如果是父节点，添加到 subsystemNames
          if (!processedSubsystems.has(nodeInfo.label)) {
            subsystemNames.push(nodeInfo.label)
            processedSubsystems.add(nodeInfo.label)
          }
        } else {
          // 如果是子节点，添加父级和子级
          if (nodeInfo.parentLabel && !processedSubsystems.has(nodeInfo.parentLabel)) {
            subsystemNames.push(nodeInfo.parentLabel)
            processedSubsystems.add(nodeInfo.parentLabel)
          }
          // 标记该子系统有子节点被选中
          if (nodeInfo.parentLabel) {
            subsystemsWithChildren.add(nodeInfo.parentLabel)
          }
          if (nodeInfo.label) {
            parameterTypes.push(nodeInfo.label)
          }
          // 构建 subsystemTypes：格式为 "子系统名称-参数类型"
          // 如果零部件名称是 `/`，则传入 `子系统-/`
          if (nodeInfo.parentLabel && nodeInfo.label) {
            const partsName = nodeInfo.label === '/' ? '/' : nodeInfo.label
            const subsystemTypeStr = `${nodeInfo.parentLabel}-${partsName}`
            if (!processedSubsystemTypes.has(subsystemTypeStr)) {
              subsystemTypes.push(subsystemTypeStr)
              processedSubsystemTypes.add(subsystemTypeStr)
            }
          }
        }
      })

      // 对于只选择了父节点（子系统）但没有选择子节点的情况，添加 `子系统-/`
      subsystemNames.forEach(subsystemName => {
        if (!subsystemsWithChildren.has(subsystemName)) {
          const subsystemTypeStr = `${subsystemName}-/`
          if (!processedSubsystemTypes.has(subsystemTypeStr)) {
            subsystemTypes.push(subsystemTypeStr)
            processedSubsystemTypes.add(subsystemTypeStr)
          }
        }
      })

      return { subsystemNames, parameterTypes, subsystemTypes }
    },
    handleRemoveModel(index) {
      const removedModel = this.comparisonModels[index]
      if (removedModel && removedModel.id) {
        // 从 allModelDetailData 中删除该机型的数据
        this.$delete(this.allModelDetailData, removedModel.id)
      }
      this.comparisonModels.splice(index, 1)
    },
    // 加载常用列表
    loadFavoritesList() {
      const request = {
        ...api.GET_USER_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.commonName || item.name || '',
              data: item // 保存完整数据，用于后续使用
            }))
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取常用列表失败:', err)
          this.$message.error('获取常用列表失败')
        })
    },
    // 常用选择变化
    handleFavoriteChange(value) {
      if (!value) {
        // 清空常用配置
        this.currentCommonConfig = null
        // 恢复完整的树数据（确保使用完整的树数据）
        this.treeData = JSON.parse(JSON.stringify(this.allTreeData))
        this.nodeMap = JSON.parse(JSON.stringify(this.allNodeMap))
        // 恢复所有隐藏的参数
        this.hiddenParams = []
        // 恢复所有选中状态（选中全部树节点）
        const allKeys = this.getAllNodeKeys(this.treeData)
        this.defaultExpandedKeys = allKeys
        this.checkedKeys = allKeys
        this.$nextTick(() => {
          if (this.$refs.paramTree && allKeys.length > 0) {
            this.$refs.paramTree.setCheckedKeys(allKeys)
          }
        })
        return
      }

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

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

      // 根据可显示的参数更新树节点选中状态
      // 注意：不再调用 hideParamsNotInCommon，而是让 displayParams 自动过滤
      // 如果树节点未选中，参数不显示（可以通过选中树节点恢复）
      // 如果树节点选中但参数不在常用中，参数不显示（即使选中树节点也不显示）
      // 确保树数据和节点映射已经准备好
      if (this.allTreeData && this.allTreeData.length > 0 && Object.keys(this.allNodeMap).length > 0) {
        this.updateCheckedKeysByDisplayParams()
      } else {
        // 如果树数据还没有加载，等待加载完成后再更新
        // 这个逻辑在 loadTreeData 的 loadAllParametersData 完成后已经处理了
        console.log('树数据还未加载完成，等待加载完成后再更新选中状态')
      }
    },
    // 下载
    handleDownloadComparisonData() {
      // 获取已添加在右侧的机型ID
      const allSelectedIds = this.comparisonModels.map(item => item.id).filter(id => id)
      if (allSelectedIds.length === 0) {
        this.$message.warning('请先添加机型')
        return
      }
      // 获取选中的参数类型
      const { subsystemTypes } = this.getSelectedSubsystemsAndTypes()
      const { url, method = 'post', headers = {} } = api.DOWNLOAD_MODEL_QUERY_DATA || {}
      const requestConfig = {
        url,
        method,
        data: {
          userID: getUserId(),
          modelIds: allSelectedIds,
          subsystemParts: subsystemTypes
        },
        responseType: 'blob',
        headers,
        disableSuccessMsg: true
      }
      this.$axios(requestConfig)
        .then((response) => {
          const blobData = response.data
          if (!blobData) {
            console.log('下载失败，文件内容为空')
            return
          }
          const contentType =
            response.headers &&
            (response.headers['content-type'] || response.headers['Content-Type'])
          if (contentType && contentType.includes('application/json')) {
            try {
              const reader = new FileReader()
              reader.onload = () => {
                console.log(`下载失败: ${reader.result}`)
              }
              reader.readAsText(blobData)
            } catch (err) {
              console.error('解析下载失败响应异常:', err)
            }
            return
          }
          const disposition =
            response.headers &&
            (response.headers['content-disposition'] || response.headers['Content-Disposition'])
          let filename = '对比数据.xlsx'
          if (disposition) {
            const filenameMatch = /filename\*=UTF-8''([^;]+)|filename="?([^";]+)"?/i.exec(
              disposition
            )
            const matchedName = filenameMatch ? filenameMatch[1] || filenameMatch[2] : ''
            if (matchedName) {
              try {
                filename = decodeURIComponent(matchedName)
              } catch (err) {
                filename = matchedName
              }
            }
          }
          const downloadUrl = window.URL.createObjectURL(blobData)
          const link = document.createElement('a')
          link.href = downloadUrl
          link.download = filename
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link)
          window.URL.revokeObjectURL(downloadUrl)
          console.log('下载开始，请查看浏览器下载列表')
        })
        .catch((err) => {
          console.error('下载失败:', err)
          console.log('下载失败，请稍后重试')
        })
        
    },
    // 根据可显示的参数更新树节点选中状态（不改变树数据）
    updateCheckedKeysByDisplayParams() {
      // 确保使用完整的树数据和节点映射
      this.treeData = JSON.parse(JSON.stringify(this.allTreeData))
      this.nodeMap = JSON.parse(JSON.stringify(this.allNodeMap))

      // 如果没有常用配置，全选所有节点
      if (!this.currentCommonConfig || !this.currentCommonConfig.subsystems) {
        const allKeys = this.getAllNodeKeys(this.treeData)
        this.checkedKeys = allKeys
        this.defaultExpandedKeys = allKeys
        this.$nextTick(() => {
          if (this.$refs.paramTree && allKeys.length > 0) {
            this.$refs.paramTree.setCheckedKeys(allKeys)
          }
        })
        return
      }

      // 从常用配置中提取所有参数，构建子系统和零部件名称的映射
      // 格式：{ subsystemName: Set<partsName> }
      const subsystemPartsMap = new Map()

      this.currentCommonConfig.subsystems.forEach(subsystemConfig => {
        const subsystemName = subsystemConfig.subsystem
        if (!subsystemPartsMap.has(subsystemName)) {
          subsystemPartsMap.set(subsystemName, new Set())
        }

        // 遍历常用配置中的参数，根据 partsName 统计零部件
        subsystemConfig.parameters.forEach(commonParam => {
          // 直接使用常用配置中的 partsName 字段
          if (commonParam.partsName) {
            const partsName = commonParam.partsName
            // 如果 partsName 是 '/'，表示选中整个子系统，使用子系统名称作为标识
            const displayPartsName = partsName === '/' ? subsystemName : partsName
            subsystemPartsMap.get(subsystemName).add(displayPartsName)
          } else {
            // 如果没有 partsName，尝试从 allParametersData 中查找匹配的参数
            const subsystemData = this.allParametersData[subsystemName]
            if (Array.isArray(subsystemData)) {
              const matchedParam = subsystemData.find(param => {
                if (commonParam.parameterId) {
                  return param.parameterId === commonParam.parameterId
                } else if (commonParam.parameterName) {
                  return param.parameterName === commonParam.parameterName
                }
                return false
              })

              if (matchedParam && matchedParam.partsName) {
                // 获取零部件名称（partsName），如果是 `/` 则使用子系统名称
                const partsName = matchedParam.partsName
                const displayPartsName = partsName === '/' ? subsystemName : partsName
                subsystemPartsMap.get(subsystemName).add(displayPartsName)
              }
            }
          }
        })
      })

      // 根据子系统和零部件名称，在树中找到对应的节点并选中
      const keysToCheck = []

      // 遍历完整的树数据
      this.allTreeData.forEach(node => {
        // 检查是否是常用中包含的子系统（一级树节点）
        // 使用精确匹配和包含匹配两种方式
        let matchedSubsystemName = null
        for (const [subsystemName] of subsystemPartsMap) {
          if (node.label === subsystemName || node.label.includes(subsystemName) || subsystemName.includes(node.label)) {
            matchedSubsystemName = subsystemName
            break
          }
        }

        if (matchedSubsystemName) {
          const partsNames = subsystemPartsMap.get(matchedSubsystemName)
          const subsystemName = matchedSubsystemName

          // 检查是否有 partsName 为 '/' 的情况（应该选中子系统节点本身）
          if (partsNames.has(subsystemName)) {
            // 如果 partsName 是 '/'，选中子系统节点（一级节点）
            keysToCheck.push(node.id)
            // 从 partsNames 中移除子系统名称，避免重复处理
            partsNames.delete(subsystemName)
          }

          // 处理其他零部件名称（二级节点）
          if (node.children && Array.isArray(node.children)) {
            if (partsNames.size > 0) {
              // 如果常用中指定了具体的零部件名称，只选中这些零部件节点（二级树节点）
              node.children.forEach(child => {
                // 检查子节点的 label 是否在 partsNames 中（支持精确匹配和包含匹配）
                for (const partsName of partsNames) {
                  if (child.label === partsName || child.label.includes(partsName) || partsName.includes(child.label)) {
                    keysToCheck.push(child.id)
                    break
                  }
                }
              })
            }
            // 注意：如果 partsNames 为空（删除子系统名称后），说明只有 partsName === '/' 的情况，
            // 已经选中了子系统节点，不需要选中子节点
          }
        }
      })

      // 更新选中状态
      this.checkedKeys = keysToCheck
      // 设置默认展开的节点（包含所有一级节点和选中的二级节点）
      const expandedKeys = []
      this.allTreeData.forEach(node => {
        // 检查是否是常用中包含的子系统
        for (const [subsystemName] of subsystemPartsMap) {
          if (node.label === subsystemName || node.label.includes(subsystemName) || subsystemName.includes(node.label)) {
            expandedKeys.push(node.id)
            break
          }
        }
      })
      expandedKeys.push(...keysToCheck)
      this.defaultExpandedKeys = expandedKeys
      this.$nextTick(() => {
        if (this.$refs.paramTree) {
          if (keysToCheck.length > 0) {
            this.$refs.paramTree.setCheckedKeys(keysToCheck)
            this.$refs.paramTree.setExpandedKeys(expandedKeys)
          } else {
            this.$refs.paramTree.setCheckedKeys([])
          }
        }
        // 如果有已添加的机型，根据新选中的树节点重新加载参数数据
        this.reloadModelDetailsForCheckedNodes()
      })
    },
    // 重建节点映射
    rebuildNodeMap(nodes, parentLabel = null) {
      nodes.forEach((node, index) => {
        const isParent = !parentLabel
        const label = node.label
        this.nodeMap[node.id] = {
          label: label,
          parentLabel: parentLabel,
          isParent: isParent
        }

        if (node.children && node.children.length > 0) {
          this.rebuildNodeMap(node.children, label)
        }
      })
    },
    // 根据常用配置隐藏不在范围内的参数
    hideParamsNotInCommon() {
      if (!this.currentCommonConfig || !this.currentCommonConfig.subsystems) {
        return
      }

      // 构建常用配置中的参数映射：subsystem -> { parameterIds: Set, parameterNames: Set }
      const commonParamsMap = new Map()
      this.currentCommonConfig.subsystems.forEach(subsystemConfig => {
        const subsystemName = subsystemConfig.subsystem
        const parameterIds = new Set(
          subsystemConfig.parameters.map(p => p.parameterId)
        )
        const parameterNames = new Set(
          subsystemConfig.parameters.map(p => p.parameterName)
        )
        commonParamsMap.set(subsystemName, { parameterIds, parameterNames })
      })

      // 遍历所有参数数据，找出不在常用配置中的参数并隐藏
      const paramsToHide = []
      Object.keys(this.allParametersData).forEach(subsystemName => {
        // 如果该子系统不在常用配置中，隐藏该子系统下的所有参数
        if (!commonParamsMap.has(subsystemName)) {
          const paramList = this.allParametersData[subsystemName]
          if (Array.isArray(paramList)) {
            paramList.forEach(item => {
              const parameterName = item.parameterName || ''
              const key = `${subsystemName}-${parameterName}`
              if (!paramsToHide.includes(key)) {
                paramsToHide.push(key)
              }
            })
          }
          return
        }

        // 如果该子系统在常用配置中，检查每个参数
        const commonParams = commonParamsMap.get(subsystemName)
        const paramList = this.allParametersData[subsystemName]
        if (Array.isArray(paramList)) {
          paramList.forEach(item => {
            const parameterName = item.parameterName || ''
            const parameterId = item.parameterId || ''

            // 检查该参数是否在常用配置中
            // 优先使用 parameterId 匹配，其次使用 parameterName 匹配
            const isInCommon = parameterId
              ? commonParams.parameterIds.has(parameterId)
              : commonParams.parameterNames.has(parameterName)

            if (!isInCommon) {
              const key = `${subsystemName}-${parameterName}`
              if (!paramsToHide.includes(key)) {
                paramsToHide.push(key)
              }
            }
          })
        }
      })

      // 将不在常用配置中的参数添加到隐藏列表
      paramsToHide.forEach(key => {
        if (!this.hiddenParams.includes(key)) {
          this.hiddenParams.push(key)
        }
      })
    },
    handleUpdateFavorite() {
      // 检查是否有已选择的"我的常用"
      if (!this.currentCommonConfig) {
        this.$message({
          type: 'warning',
          message: '请先选择一个常用配置'
        })
        return
      }

      // 检查是否有展示的参数
      if (this.displayParams.length === 0) {
        this.$message({
          type: 'warning',
          message: '当前没有可保存的参数，请先选择参数'
        })
        return
      }

      // 收集当前展示的参数数据
      const saveData = this.collectCurrentDisplayParams()

      if (!saveData || !saveData.subsystems || saveData.subsystems.length === 0) {
        this.$message({
          type: 'warning',
          message: '当前没有可保存的参数'
        })
        return
      }

      // 构建参数ID数组
      let parameters = []
      saveData.subsystems.forEach(item => {
        item.parameters.forEach(param => {
          parameters.push(param.parameterId)
        })
      })

      // 构建更新数据（和新增一样，但使用当前选中的常用配置的 commonName）
      const requestData = {
        userId: getUserId(),
        commonName: this.currentCommonConfig.commonName || this.currentCommonConfig.name,
        parameters: parameters
      }

      // 如果有 commonId，添加到请求数据中
      if (this.currentCommonConfig.commonId) {
        requestData.commonId = this.currentCommonConfig.commonId
      } else if (this.currentCommonConfig.id) {
        requestData.id = this.currentCommonConfig.id
      }

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

      this.$request(request)
        .asyncThen((resp) => {
          // this.$message.success('更新常用成功')
          // 重新加载常用列表
          this.loadFavoritesList()
        })
        .asyncErrorCatch((err) => {
          console.error('更新常用失败:', err)
          this.$message.error(err.message || '更新常用失败')
        })
        .finally(() => {
          this.savingFavorite = false
        })
    },
    handleAddFavorite() {
      // 检查是否有展示的参数
      if (this.displayParams.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.displayParams.length === 0) {
          this.$message({
            type: 'warning',
            message: '当前没有可保存的参数'
          })
          return
        }

        // 收集当前展示的参数数据
        const saveData = this.collectCurrentDisplayParams()

        if (!saveData || !saveData.subsystems || saveData.subsystems.length === 0) {
          this.$message({
            type: 'warning',
            message: '当前没有可保存的参数'
          })
          return
        }
        let parameters = []
        saveData.subsystems.forEach(item => {
          item.parameters.forEach(param => {
            parameters.push(param.parameterId)
          })
        })
        // 构建保存数据
        const requestData = {
          userId: getUserId(),
          commonName: this.addFavoriteFormData.commonName,
          parameters: parameters
        }

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

        this.$request(request)
          .asyncThen((resp) => {
            // this.$message.success('新增常用成功')
            this.handleAddFavoriteDialogClose()
            // 重新加载常用列表
            this.loadFavoritesList()
          })
          .asyncErrorCatch((err) => {
            console.error('新增常用失败:', err)
            this.$message.error(err.message || '新增常用失败')
          })
          .finally(() => {
            this.savingFavorite = false
          })
      })
    },
    // 收集当前展示的参数数据
    collectCurrentDisplayParams() {
      // 按照子系统分组收集参数
      const subsystemMap = new Map() // key: subsystemName, value: { subsystem, parameters: [] }

      // 遍历当前展示的参数
      this.displayParams.forEach(param => {
        const subsystemName = param.subsystemName

        // 如果该子系统还没有在 map 中，创建它
        if (!subsystemMap.has(subsystemName)) {
          subsystemMap.set(subsystemName, {
            subsystem: subsystemName,
            parameters: []
          })
        }

        // 优先使用 displayParams 中已有的 parameterId
        let parameterId = param.parameterId || null

        // 如果 displayParams 中没有 parameterId，从 allParametersData 中查找
        if (!parameterId && this.allParametersData[subsystemName]) {
          const paramList = this.allParametersData[subsystemName]
          if (Array.isArray(paramList)) {
            const matchedParam = paramList.find(item => {
              return item.parameterName === param.parameterName
            })
            if (matchedParam && matchedParam.parameterId) {
              parameterId = matchedParam.parameterId
            }
          }
        }

        // 如果找到了 parameterId，添加到参数列表（去重）
        if (parameterId) {
          const subsystemData = subsystemMap.get(subsystemName)
          const exists = subsystemData.parameters.some(p => p.parameterId === parameterId)
          if (!exists) {
            subsystemData.parameters.push({
              parameterId: parameterId,
              parameterName: param.parameterName
            })
          }
        } else {
          // 如果找不到 parameterId，使用 parameterName（去重）
          const subsystemData = subsystemMap.get(subsystemName)
          const exists = subsystemData.parameters.some(p => p.parameterName === param.parameterName)
          if (!exists) {
            subsystemData.parameters.push({
              parameterId: '', // 如果没有 parameterId，留空
              parameterName: param.parameterName
            })
          }
        }
      })

      // 转换为数组格式
      const subsystems = Array.from(subsystemMap.values())

      return {
        subsystems: subsystems
      }
    },
    // 隐藏参数
    handleHideParam(param) {
      // 使用新的 key 格式：subsystemName-parameterName
      const key = `${param.subsystemName}-${param.parameterName}`
      if (!this.hiddenParams.includes(key)) {
        this.hiddenParams.push(key)
        // this.$message.success('参数已隐藏')
      }
    },
    // 显示已隐藏参数弹窗
    handleShowHiddenParams() {
      // 打开弹窗时，清空之前的选择
      this.selectedParamsToRestore = []
      this.hiddenParamsDialogVisible = true
      // 清空表格选择
      this.$nextTick(() => {
        if (this.$refs.hiddenParamsTable) {
          this.$refs.hiddenParamsTable.clearSelection()
        }
      })
    },
    // 关闭已隐藏参数弹窗
    handleHiddenParamsDialogClose() {
      this.hiddenParamsDialogVisible = false
      // 关闭时清空选中的参数
      this.selectedParamsToRestore = []
      // 清空表格选择
      if (this.$refs.hiddenParamsTable) {
        this.$refs.hiddenParamsTable.clearSelection()
      }
    },
    // 处理表格选择变化
    handleHiddenParamsSelectionChange(selection) {
      // 将选中的行转换为 key 数组
      this.selectedParamsToRestore = selection.map(row => {
        return row.key || `${row.subsystemName}-${row.parameterName}`
      })
    },
    // 全部恢复
    handleRestoreAll() {
      if (this.hiddenParamsList.length === 0) {
        this.$message({
          type: 'warning',
          message: '没有可恢复的参数'
        })
        return
      }
      // 选中所有行
      this.$nextTick(() => {
        if (this.$refs.hiddenParamsTable) {
          this.$refs.hiddenParamsTable.toggleAllSelection()
        }
      })
    },
    // 恢复已选择
    handleRestoreSelected() {
      if (this.selectedParamsToRestore.length === 0) {
        this.$message({
          type: 'warning',
          message: '请至少选择一个要恢复的参数'
        })
        return
      }
      // 执行恢复操作
      this.executeRestoreParams(this.selectedParamsToRestore)
    },
    // 确认恢复参数（批量从隐藏列表中移除）
    handleConfirmRestoreParams() {
      if (this.selectedParamsToRestore.length === 0) {
        this.$message({
          type: 'warning',
          message: '请至少选择一个要恢复的参数'
        })
        return
      }
      // 执行恢复操作
      this.executeRestoreParams(this.selectedParamsToRestore)
    },
    // 执行恢复参数操作
    executeRestoreParams(keysToRestore) {
      if (!keysToRestore || keysToRestore.length === 0) {
        return
      }

      // 从 hiddenParams 中移除选中的参数
      keysToRestore.forEach(key => {
        const index = this.hiddenParams.indexOf(key)
        if (index > -1) {
          this.hiddenParams.splice(index, 1)
        }
      })

      // 清空选中的列表
      this.selectedParamsToRestore = []
      // 清空表格选择
      if (this.$refs.hiddenParamsTable) {
        this.$refs.hiddenParamsTable.clearSelection()
      }
      // 关闭弹窗
      this.hiddenParamsDialogVisible = false
      // this.$message.success(`已恢复 ${restoreCount} 个参数`)
    },
    // 加载树数据
    loadTreeData() {
      const request = {
        ...api.GET_ENGINE_DETAIL_QUERY,
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          // 处理接口返回的数据
          if (resp && resp.data) {
            // 接口返回的是对象格式：{ "父节点名": ["子节点1", "子节点2", ...] }
            const data = resp.data
            let treeDataResult = []
            if (typeof data === 'object' && !Array.isArray(data)) {
              treeDataResult = this.convertObjectToTree(data)
            } else if (Array.isArray(data)) {
              // 如果已经是数组格式，尝试格式化
              treeDataResult = this.formatTreeData(data)
            } else {
              treeDataResult = []
            }

            // 保存完整的树数据（未过滤）
            this.allTreeData = JSON.parse(JSON.stringify(treeDataResult))
            this.allNodeMap = JSON.parse(JSON.stringify(this.nodeMap))

            // 始终使用完整的树数据
            this.treeData = JSON.parse(JSON.stringify(this.allTreeData))

            // 加载所有参数数据（先加载参数数据，再根据常用配置更新选中状态）
            this.loadAllParametersData().then(() => {
              // 如果已选择常用配置，根据可显示的参数更新选中状态
              if (this.currentCommonConfig) {
                // 先隐藏不在常用范围内的参数
                // 不再调用 hideParamsNotInCommon，让 displayParams 自动过滤
                // 然后根据可显示的参数更新树节点选中状态
                this.$nextTick(() => {
                  this.updateCheckedKeysByDisplayParams()
                })
              } else {
                // 否则全选
                const allKeys = this.getAllNodeKeys(this.treeData)
                this.defaultExpandedKeys = allKeys
                this.checkedKeys = allKeys
                // 使用 $nextTick 确保树组件渲染完成后再设置选中状态
                this.$nextTick(() => {
                  // 使用 setCheckedKeys 方法设置全选状态
                  if (this.$refs.paramTree && allKeys.length > 0) {
                    this.$refs.paramTree.setCheckedKeys(allKeys)
                  }
                })
              }
            })
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取参数列表失败:', err)
          this.$message.error('获取参数列表失败')
        })
    },
    // 加载所有参数数据
    loadAllParametersData() {
      const request = {
        ...api.GET_ALL_DATA_SYSTEAM_LIST,
        disableSuccessMsg: true
      }
      return this.$request(request)
        .asyncThen((resp) => {
          if (resp && resp.data) {
            // 处理返回的数据，将数组格式转换为对象格式
            // 输入格式: [{ subsystem: "子系统名称", parameters: [{ parameterId, parameterName, partsName }] }]
            // 输出格式: { "子系统名称": [{ parameterId, parameterName, partsName, subsystem }] }
            const result = {}
            if (Array.isArray(resp.data)) {
              resp.data.forEach(item => {
                if (item.subsystem && Array.isArray(item.parameters)) {
                  result[item.subsystem] = item.parameters.map(param => ({
                    parameterId: param.parameterId || '',
                    parameterName: param.parameterName || '',
                    partsName: param.partsName || '',
                    subsystem: item.subsystem // 保存子系统名称
                  }))
                }
              })
            }
            this.allParametersData = result
            // 参数数据加载完成后，调用获取常用列表
            this.loadFavoritesList()
          } else {
            this.allParametersData = {}
            // 即使没有数据，也调用获取常用列表
            this.loadFavoritesList()
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取所有参数数据失败:', err)
          this.allParametersData = {}
          // 即使失败，也调用获取常用列表
          this.loadFavoritesList()
        })
    },
    // 将对象格式转换为树形结构
    // 输入格式: { "父节点名": ["子节点1", "子节点2", ...] }
    convertObjectToTree(data) {
      const treeData = []
      this.nodeMap = {} // 重置节点映射

      Object.keys(data).forEach((parentLabel, parentIdx) => {
        const parentId = `parent-${parentIdx}`
        const children = []
        const seenLabels = new Set() // 用于去重，记录已处理的子节点 label

        // 保存父节点映射
        this.nodeMap[parentId] = {
          label: parentLabel,
          parentLabel: null,
          isParent: true
        }

        // 处理子节点数组，去重（根据 label），过滤掉值为 `/` 的子节点
        if (Array.isArray(data[parentLabel])) {
          data[parentLabel].forEach((childLabel, childIdx) => {
            // 过滤掉值为 `/` 的子节点
            if (childLabel === '/') {
              return
            }
            // 如果该 label 已经处理过，跳过
            if (seenLabels.has(childLabel)) {
              return
            }
            seenLabels.add(childLabel)

            const childId = `${parentId}-${childIdx}`
            children.push({
              id: childId,
              label: childLabel,
              tip: ''
            })
            // 保存子节点映射
            this.nodeMap[childId] = {
              label: childLabel,
              parentLabel: parentLabel,
              isParent: false
            }
          })
        }

        treeData.push({
          id: parentId,
          label: parentLabel,
          tip: '',
          children: children
        })
      })

      return treeData
    },
    // 格式化树数据，确保每个节点有 id 和 label 属性，并对子节点去重（根据 label）
    formatTreeData(data) {
      return data.map((item, index) => {
        const node = {
          id: item.id || item.key || `node-${index}`,
          label: item.label || item.name || item.title || '',
          tip: item.tip || ''
        }
        if (item.children && item.children.length > 0) {
          // 对子节点去重（根据 label）
          const seenLabels = new Set()
          const uniqueChildren = []
          item.children.forEach((child) => {
            const childLabel = child.label || child.name || child.title || ''
            if (!seenLabels.has(childLabel)) {
              seenLabels.add(childLabel)
              uniqueChildren.push(child)
            }
          })
          // 递归处理子节点
          node.children = this.formatTreeData(uniqueChildren)
        }
        return node
      })
    },
    // 获取所有节点的keys
    getAllNodeKeys(nodes) {
      let keys = []
      nodes.forEach(node => {
        keys.push(node.id)
        if (node.children && node.children.length > 0) {
          keys = keys.concat(this.getAllNodeKeys(node.children))
        }
      })
      return keys
    },
    // 加载机型数据（用于弹窗选择，与 loadModelListForDialog 功能相同，保留以备用）
    loadComparisonModels() {
      this.loadModelListForDialog()
    }
  }
}
</script>

<style lang="scss" scoped>
.model-query-tab {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;

  .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%;

      .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;
        }
      }
    }
  }

  .model-query-content {
    display: flex;
    flex: 1;
    overflow: hidden;
    background: #f5f7fa;

    .left-param-panel {
      width: 280px;
      background: white;
      border: 1px solid #ebeef5;
      padding: 12px;
      font-size: 14px;
      overflow-y: auto !important;
      display: flex;
      flex-direction: column;
      flex-shrink: 0;

      .tree-search-header {
        margin-bottom: 8px;
        .search-mode-switch {
          width: 100%;
          display: flex;
          ::v-deep .el-radio-button {
            flex: 1;
            .el-radio-button__inner {
              width: 100%;
              padding: 5px 8px;
              font-size: 12px;
            }
          }
        }
      }
      .tree-search {
        margin-bottom: 8px;
      }

      .custom-tree-node {
        display: inline-flex;
        align-items: center;
        gap: 6px;
      }

      .red-tip {
        color: #f56c6c;
        white-space: pre-line;
      }
    }

    .right-comparison-panel {
      flex: 1;
      overflow: auto;
      background: white;

      .comparison-table-wrapper {
        width: 100%;
        overflow-x: auto;

        .comparison-table {
          width: 100%;
          border-collapse: collapse;
          min-width: 800px;

          thead {
            background: #f5f7fa;

            th {
              padding: 12px;
              text-align: left;
              border: 1px solid #ebeef5;
              font-weight: 500;
              font-size: 14px;
              color: #303133;

              &.param-column {
                width: 200px;
                min-width: 200px;
                position: sticky;
                left: 0;
                background: #f5f7fa;
                z-index: 10;
              }

              &.model-column {
                min-width: 180px;
                text-align: center;
              }

              &.add-column {
                min-width: 150px;
                text-align: center;
              }
            }

            .model-header {
              display: flex;
              flex-direction: column;
              align-items: center;
              gap: 8px;
              position: relative;

              .model-image {
                width: 120px;
                height: 80px;
                object-fit: contain;
                border-radius: 4px;
              }

              .model-name {
                font-size: 14px;
                color: #303133;
              }

              .model-remove {
                position: absolute;
                top: -8px;
                right: -8px;
                cursor: pointer;
                color: #909399;
                font-size: 16px;
                background: white;
                border-radius: 50%;
                width: 20px;
                height: 20px;
                display: flex;
                align-items: center;
                justify-content: center;

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

              .add-model-placeholder {
                width: 120px;
                height: 80px;
                border: 2px dashed #dcdfe6;
                border-radius: 4px;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                color: #909399;
                transition: all 0.3s;

                &:hover {
                  border-color: #409EFF;
                  color: #409EFF;
                  background: #ecf5ff;
                }

                i {
                  font-size: 24px;
                  margin-bottom: 4px;
                }

                span {
                  font-size: 12px;
                }
              }
            }
          }

          tbody {
            tr {
              &:hover {
                background: #f5f7fa;
              }

              td {
                padding: 12px;
                border: 1px solid #ebeef5;
                font-size: 14px;
                color: #606266;

                &.param-column {
                  position: sticky;
                  left: 0;
                  background: white;
                  z-index: 5;
                  display: flex;
                  align-items: center;
                  gap: 8px;

                  .param-name {
                    flex: 1;
                  }

                  .param-config-icon {
                    cursor: pointer;
                    color: #909399;
                    font-size: 14px;

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

                &.model-column {
                  text-align: center;
                }

                &.add-column {
                  background: #fafafa;
                }
              }
            }
          }
        }
      }
    }
  }

  .hidden-params-dropdown {
    margin-left: 12px;
  }

  .hidden-params-button {
    margin-left: 12px;

    .hidden-count {
      margin-left: 4px;
      color: #f56c6c;
      font-weight: 500;
    }
  }

  .model-select-dialog {
    .model-search-input {
      margin-bottom: 16px;
    }

    .model-list-wrapper {
      .el-table {
        border: 1px solid #ebeef5;
      }
    }
  }

  .hidden-params-dialog-content {
    .empty-hint {
      text-align: center;
      padding: 40px 0;
      color: #909399;
      font-size: 14px;
    }

    .hidden-params-header {
      display: flex;
      gap: 8px;
      margin-bottom: 12px;
      padding-bottom: 12px;
      border-bottom: 1px solid #ebeef5;
    }
  }
}
.v-modal{
  display: none !important;
}
</style>
