<template>
  <div class="engine-detail-page custom-page">
    <div class="page-header">
      <div class="header-left">
        <el-button
          type="text"
          icon="el-icon-arrow-left"
          class="back-button"
          @click.stop="handleBack"
        >
          返回
        </el-button>
        <div class="header-item">
          <span class="label">版本:</span>
          <span class="value">{{ currentVersionLabel }}</span>
        </div>
      </div>
      <div v-if="!isApprovalMode" class="operation">
        <template v-if="isDispatchMode">
          <el-button size="small" @click="handleBatchModifyResponsible">
            {{ dispatchType === 'update_param' ? '批量修改填写人' : '批量修改责任人' }}
          </el-button>
          <!-- <el-button size="small" @click="handleSave">保存</el-button> -->
          <el-button type="primary" size="small" @click="handleConfirmDispatch">确认分发</el-button>
        </template>
        <template v-else>
          <el-select
            v-model="currentVersionId"
            size="small"
            @change="onVersionChange"
            :disabled="isEditMode"
          >
            <el-option v-for="ver in versions" :key="ver.id" :label="ver.label" :value="ver.id" />
          </el-select>
          <el-button
            v-if="!isEditMode && !isJustCheckMode"
            size="small"
            style="margin-left: 12px;"
            @click="handleExportTemplate"
            >下载导入模板</el-button
          >
          <el-button
            v-if="!isEditMode && !isJustCheckMode"
            size="small"
            :disabled="importing"
            :loading="importing"
            @click="handleImport"
            >导入</el-button
          >
          <input
            ref="fileInput"
            type="file"
            style="display: none"
            accept=".xlsx,.xls"
            @change="handleFileChange"
          />
          <template v-if="!isEditMode && !isJustCheckMode">
            <el-button size="small" @click="handleEdit"
              >编辑</el-button
            >
            <el-button
              type="primary"
              size="small"
              @click="handleInitiateApproval"
              >发起审批</el-button
            >
          </template>
          <template v-else-if="isEditMode">
            <el-button size="small" @click="handleSaveEdit">保存编辑</el-button>
            <el-button size="small" @click="handleCancelEdit">取消</el-button>
          </template>
        </template>
      </div>
    </div>

    <div v-if="!isApprovalMode" class="detail-body">
      <div class="left-tree-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>
        <!-- <div class="tree-actions">
          <el-button size="mini" @click="handleExpandAllSecondLevel">
            一键展开
          </el-button>
          <el-button size="mini" @click="handleCollapseAllSecondLevel">
            一键收起
          </el-button>
        </div> -->
        <el-tree
          ref="paramTree"
          :data="treeData"
          node-key="id"
          show-checkbox
          :checked-keys="checkedKeys"
          :default-expanded-keys="defaultExpandedKeys"
          :expanded-keys="expandedKeys"
          :props="{ children: 'children', label: 'label' }"
          :filter-node-method="filterTreeNode"
          :draggable="true"
          :allow-drop="allowDrop"
          :allow-drag="allowDrag"
          @check="handleTreeCheck"
          @node-drop="handleNodeDrop"
          @node-expand="handleNodeExpand"
          @node-collapse="handleNodeCollapse"
        >
          <span class="custom-tree-node" slot-scope="{ data }">
            <span>{{ data.label }}</span>
            <span v-if="data.tip" class="red-tip">{{ data.tip }}</span>
          </span>
        </el-tree>
      </div>

      <div class="right-content">
        <!-- 整车参数表格 -->
        <template v-for="(sectionData, sectionKey) in wholeEngineParamsData">
          <div v-if="isWholeEngineParamsSelected" class="section" :key="sectionKey">
            <div class="section-title">{{ sectionKey }}</div>
            <div class="grid whole-engine-grid">
              <div class="grid-header whole-engine-header">
                <div class="cell header-cell">参数名称</div>
                <div class="cell header-cell">单位</div>
                <div class="cell header-cell">参数值</div>
              </div>
              <div
                class="grid-row whole-engine-row"
                v-for="(row, idx) in sectionData"
                :key="sectionKey + '-' + idx"
              >
                <div class="cell">{{ row.parameterName }}</div>
                <div class="cell">
                  <span>{{ row.unit || '-' }}</span>
                </div>
                <div class="cell">
                  <span>{{ row.parameterValue || '/' }}</span>
                </div>
              </div>
            </div>
          </div>
        </template>
        <!-- 子系统参数表格 -->
        <template v-for="(sectionData, sectionKey) in display">
          <div class="section" v-if="shouldShowSection(sectionKey)" :key="sectionKey">
            <div class="section-title">{{ formatSectionTitle(sectionKey, sectionData) }}</div>
            <div class="grid">
              <div class="grid-header" :class="{ 'edit-mode': isEditMode && !isDispatchMode }">
                <div class="cell header-cell">参数名称</div>
                <div class="cell header-cell">单位</div>
                <div class="cell header-cell">参数值</div>
                <div class="cell header-cell" v-if="!isEditMode || isDispatchMode">填写部门</div>
                <div class="cell header-cell" v-if="!isEditMode || isDispatchMode">
                  {{
                    isDispatchMode && dispatchType === 'update_param'
                      ? '填写人'
                      : isDispatchMode
                      ? '责任人'
                      : '填写人'
                  }}
                </div>
              </div>
              <div
                class="grid-row"
                v-for="(row, idx) in sectionData"
                :key="sectionKey + '-' + idx"
                :class="{ 'edit-mode': isEditMode && !isDispatchMode }"
              >
                <div class="cell">{{ row.parameterName }}</div>
                <div class="cell">
                  <span>{{ row.unit || '-' }}</span>
                </div>
                <div class="cell">
                  <el-input
                    v-if="isEditMode && !isDispatchMode"
                    v-model="row.parameterValue"
                    size="small"
                    placeholder="请输入"
                    class="param-input"
                  />
                  <span v-else>{{ row.minorVersion || row.parameterValue || '/' }}</span>
                </div>
                <div v-if="!isEditMode || isDispatchMode" class="cell">
                  <span>{{ formatDepartmentDisplay(row.department) }}</span>
                </div>
                <!-- 责任人列：分发模式下且不是 update_param 类型时显示，只读（只能通过批量修改更改） -->
                <div v-if="isDispatchMode && dispatchType !== 'update_param'" class="cell">
                  <span>{{ row.owner || '-' }}</span>
                </div>
                <!-- 填写人列：分发模式下且是 update_param 类型时显示，可编辑 -->
                <div v-if="isDispatchMode && dispatchType === 'update_param'" class="cell">
                  <el-select
                    v-model="row.filledByUserId"
                    size="small"
                    placeholder="请输入填写人姓名进行搜索"
                    class="responsible-select"
                    clearable
                    filterable
                    remote
                    reserve-keyword
                    :remote-method="(query) => handleFillerRemoteSearch(query, row)"
                    :loading="fillerUserLoading"
                    @change="(value) => handleFillerChange(value, row)"
                  >
                    <el-option
                      v-for="person in getFillerUserOptions(row)"
                      :key="person.userId"
                      :value="person.userId"
                      :label="person.username"
                    >
                      <span class="username-text">{{ person.username }}</span>
                      <span class="user-id-text">{{ person.userNumber }}</span>
                    </el-option>
                  </el-select>
                </div>
                <!-- 填写人列：只在非分发模式下显示，只读 -->
                <div v-if="!isDispatchMode && !isEditMode" class="cell">
                  <span>{{ row.filledBy ||  '-' }}</span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>

    <!-- 审批内容区域 -->
    <div v-if="isApprovalMode" class="page-approval-content">
      <div class="approval-content">
        <!-- 变更数据表格 -->
        <div
          v-if="approvalChangeData && approvalChangeData.length > 0"
          class="approval-change-table"
        >
          <div class="change-table-title">
            变更数据
          </div>
          <div class="change-table-wrapper">
            <table class="change-table-content">
              <thead>
                <tr>
                  <th class="col-engine-model-name">机型名称</th>
                  <th class="col-subsystem-name">子系统名称</th>
                  <th class="col-parameter-type">参数类型</th>
                  <th class="col-parts-name">零件名称</th>
                  <th class="col-parameter-name">参数名称</th>
                  <th class="col-parameter-value">参数值</th>
                  <th class="col-common">修改描述</th>
                </tr>
              </thead>
              <tbody>
                <tr
                  v-for="(item, index) in approvalChangeData"
                  :key="index"
                  class="change-table-row"
                >
                  <td class="col-engine-model-name">{{ item.engineModelName || '-' }}</td>
                  <td class="col-subsystem-name">{{ item.subsystemName || '-' }}</td>
                  <td class="col-parameter-type">{{ (item.partsName === '/' ? item.subsystemName : item.partsName) || '-' }}</td>
                  <td class="col-parts-name">{{ (item.partsName === '/' ? item.subsystemName : item.partsName) || '-' }}</td>
                  <td class="col-parameter-name">{{ item.parameterName || '-' }}</td>
                  <td class="col-parameter-value">{{ item.parameterValue || '-' }}</td>
                  <td class="col-common">{{ item.changeComment || '-' }}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>

        <!-- 流程主题 -->
       

        <!-- 说明 -->
        <div class="approval-description">
          <div class="description-label">
            说明
          </div>
          <el-input
            v-model="approvalFormData.description"
            type="textarea"
            :rows="2"
            placeholder="请输入"
          />
        </div>

        <!-- 审批环节 -->
        <div class="approval-workflow">
          <div class="workflow-title">
            审批环节
          </div>
          <div class="approval-process-title">
          <div class="description-label">
            流程主题 <span class="required-mark">*</span>
          </div>
          <el-input
            v-model="approvalFormData.processTitle"
            maxlength="100"
            show-word-limit
            placeholder="请输入流程主题"
          />
        </div>
          <div class="workflow-table">
            <table class="workflow-table-content">
              <thead>
                <tr>
                  <th class="step-name-col">
                    环节名称
                  </th>
                  <th class="handler-col">
                    处理人
                  </th>
                </tr>
              </thead>
              <tbody>
                <tr
                  v-for="(step, index) in approvalWorkflowSteps"
                  :key="index"
                  class="workflow-row"
                >
                  <td class="step-name-cell">
                    <span class="step-name">
                      {{ step.name }}
                      <span v-if="step.required" class="required-mark">*</span>
                    </span>
                  </td>
                  <td class="handler-cell">
                    <el-select
                      v-model="step.handlers"
                      multiple
                      filterable
                      remote
                      reserve-keyword
                      placeholder="请选择"
                      :remote-method="(query) => handleRemoteSearch(query, index)"
                      :loading="step.loading"
                      class="handler-select"
                      @change="(value) => handleHandlerChange(index, value)"
                    >
                      <el-option
                        v-for="person in step.options"
                        :key="person.userNumber"
                        :value="person.userId"
                        :label="person.username"
                      >
                        <span class="username-text">{{ person.username }}</span>
                        <span class="user-id-text">{{ person.userNumber }}</span>
                      </el-option>
                    </el-select>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- 审批底部操作按钮 -->
    <div v-if="isApprovalMode" class="page-footer">
      <div class="footer-buttons">
        <el-button @click="handleApprovalCancel">
          取消
        </el-button>
        <el-button type="primary" :loading="approvalSubmitting" @click="handleApprovalFormSubmit">
          确定
        </el-button>
      </div>
    </div>

    <!-- 批量修改责任人弹窗 -->
    <batch-modify-responsible-modal
      ref="batchModifyResponsibleModal"
      :responsible-persons="responsiblePersons"
      :filler-persons="fillerPersons"
      :dispatch-type="dispatchType"
      :version-data="versionData"
      :current-version-id="currentVersionId"
      @confirm="handleBatchModifyConfirm"
      @refresh-responsible-persons="loadResponsiblePersons"
    />
  </div>
</template>

<script>
import api from '@/api'
import BatchModifyResponsibleModal from './batch-modify-responsible-modal.vue'
import { getUserId } from '@/utils'

export default {
  name: 'EngineDetail',
  components: {
    BatchModifyResponsibleModal
  },
  props: {
    model: {
      type: String,
      default: ''
    },
    engineModelID: {
      type: String,
      default: ''
    },
    isDispatchMode: {
      type: Boolean,
      default: false
    },
    // 分发类型：'responsible' 表示分发填写人，'todo' 表示分发责任人
    dispatchType: {
      type: String,
      default: 'todo' // 默认为分发责任人
    },
    // 管理员分发责任人时传递的 responsiblePersonId
    responsiblePersonId: {
      type: String,
      default: ''
    },
    // 填写发动机参数值时传递的 filledBy
    filledBy: {
      type: String,
      default: ''
    },
    // 机型详情信息（包含 modelName 和 projectNumber）
    detail: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      isEditMode: false,
      originalData: null, // 保存原始数据，用于取消编辑
      dispatchOriginalData: null, // 保存分发模式下的原始数据，用于比较责任人变化
      savedCheckedKeys: [], // 保存编辑前的选中节点
      savedDefaultExpandedKeys: [], // 保存编辑前的展开节点
      currentVersionId: 'v3',
      treeFilterText: '',
      treeSearchMode: 'subsystem', // 搜索模式：'subsystem' 搜索子系统，'parts' 搜索零部件名称
      checkedKeys: [],
      expandedKeys: [], // 当前展开的节点keys（用于动态控制展开/收起）
      // 树节点映射：id -> { label, parentLabel, isParent }
      nodeMap: {},
      responsiblePersons: [], // 责任人列表（从 GET_MANAGER_DATA 接口获取）
      fillerPersons: [], // 填写人列表（从 GET_FILLER_DATA 接口获取）
      fillerUserOptions: {}, // 填写人选项（按行存储，key: rowId, value: [userOptions]）
      fillerUserLoading: false, // 填写人搜索loading状态
      // 树节点ID到右侧数据部分的映射
      versions: [],
      treeData: [],
      defaultExpandedKeys: [],
      currentEngineModelID: '', // 当前机型ID
      versionData: {},
      changeData: [], // 存储修改的数据项
      importing: false, // 导入中状态
      isApprovalMode: false, // 发起审批模式状态
      engineDetailInfo: null, // 机型详情信息（包含 modelName 和 projectNumber）
      wholeEngineParamsRawData: [], // 存储"整车参数"的原始第三级数据（数组格式）
      approvalFormData: {
        processTitle: '',
        description: ''
      },
      approvalSubmitting: false, // 审批提交loading状态
      approvalChangeData: [], // 审批变更数据
      approvalWorkflowSteps: [
        {
          name: '校对',
          required: true,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '审核',
          required: true,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '会签',
          required: false,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '批准',
          required: true,
          handlers: [],
          options: [],
          loading: false
        }
      ]
    }
  },
  computed: {
    display() {
      // 返回当前版本的数据，按参数类型分组
      const data = this.versionData[this.currentVersionId] || {}
      console.log('data', data)
      return data
    },
    currentVersionLabel() {
      const version = this.versions.find((v) => v.id === this.currentVersionId)
      return version ? version.label : 'V1'
    },
    // 判断是否是查看模式（justCheck）
    isJustCheckMode() {
      return this.dispatchType === 'justCheck'
    },
    // 检查是否选中了"整车参数"节点
    isWholeEngineParamsSelected() {
      if (!this.checkedKeys || this.checkedKeys.length === 0) {
        return false
      }
      // 检查是否有选中的节点是"整车参数"
      return this.checkedKeys.some(nodeId => {
        const nodeInfo = this.nodeMap[nodeId]
        return nodeInfo && nodeInfo.isWholeEngineParams && nodeInfo.label === '整车参数'
      })
    },
    // 将整车参数转换为参数格式
    wholeEngineParamsData() {
      // 从保存的原始数据中获取"整车参数"的第三级数据
      if (!this.wholeEngineParamsRawData || this.wholeEngineParamsRawData.length === 0) {
        return {}
      }
      // 将第三级参数名称转换为参数数组格式
      const params = this.wholeEngineParamsRawData.map((paramName) => {
        // 解析参数名称，格式是 "参数名称:参数值"
        let parameterName = paramName
        let parameterValue = '-'
        if (paramName && paramName.includes(':')) {
          const parts = paramName.split(':')
          parameterName = parts[0] || paramName
          parameterValue = parts[1] || '-'
        } else if (paramName) {
          // 如果没有冒号，整个字符串作为参数名称
          parameterName = paramName
          parameterValue = '-'
        }
        return {
          parameterName: parameterName,
          partsName: '整车参数',
          parameterValue: parameterValue,
          unit: '-',
          department: '平台部',
          subsystemName: '整车参数'
        }
      })
      // 返回按参数类型分组的格式，与其他子系统参数保持一致
      return {
        '整车参数': params
      }
    }
  },
  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)
      }
    },
    isDispatchMode(newVal) {
      // 当进入分发模式时，保存原始数据
      if (newVal && !this.dispatchOriginalData) {
        this.dispatchOriginalData = JSON.parse(JSON.stringify(this.versionData))
      }
      // 当退出分发模式时，清空原始数据
      if (!newVal) {
        this.dispatchOriginalData = null
      }
    }
  },
  created() {
    // // 获取 engineModelID，优先使用 props，其次使用 route query
    // if (
    //   !this.engineModelID &&
    //   this.$route &&
    //   this.$route.query &&
    //   this.$route.query.engineModelID
    // ) {
    //   this.currentEngineModelID = this.$route.query.engineModelID
    // } else {
    //   this.currentEngineModelID = this.engineModelID
    // }
    // // 保存机型详情信息
    // if (this.detail && Object.keys(this.detail).length > 0) {
    //   this.engineDetailInfo = this.detail
    // } else {
    //   // 如果没有传递 detail，尝试从接口获取
    // }
    // initialize version data for v2/v3 as example variations
    // 加载权限数据
    // this.loadUserSelfRole()
    // 加载责任人列表和填写人列表
    this.loadResponsiblePersons()
    this.loadFillerPersons()
    // 加载树数据
    this.loadTreeData()
    // this.loadEngineDetailInfo()
  },
  methods: {
    getversions() {
      const request = {
        ...api.GET_ENGINE_VERSIONS,
        params: {
          modelId: this.currentEngineModelID
        }
      }
      this.$request(request)
        .asyncThen((resp) => {
          if (resp && resp.data) {
            this.versions = resp.data
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取版本数据失败:', err)
        })
    },
    // 加载用户自身角色权限
    loadUserSelfRole() {
      const request = {
        ...api.GET_USER_SELF_ROLE,
        params: {
          userOrDepID: getUserId()
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          if (resp && resp.data) {
            // 将权限数据存储到 localStorage
            try {
              localStorage.setItem('user_self_role', JSON.stringify(resp.data))
            } catch (err) {
              console.error('存储权限数据到 localStorage 失败:', err)
            }
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取用户自身角色失败:', err)
        })
    },
    // 检查权限
    // menuPath: 模块路径，如 "数据录入/玉柴发动机数据" 或 "数据录入/竞品发动机数据"
    // subsystem: 子系统名称（可选，如果提供则检查该子系统的权限）
    // permissionType: 权限类型，"查看" 或 "编辑"
    checkPermission(menuPath, subsystem = null, permissionType = '查看') {
      try {
        const permissionDataStr = localStorage.getItem('user_self_role')
        if (!permissionDataStr) {
          return false
        }
        const permissionData = JSON.parse(permissionDataStr)
        if (!Array.isArray(permissionData)) {
          return false
        }

        // 查找匹配的权限
        const matchedPermissions = permissionData.filter((perm) => {
          // 检查 menuPath 是否匹配（支持包含关系）
          const menuMatch =
            perm.menuPath &&
            menuPath &&
            (perm.menuPath.includes(menuPath) || menuPath.includes(perm.menuPath))
          if (!menuMatch) {
            return false
          }

          // 如果提供了 subsystem，检查是否匹配
          if (subsystem) {
            if (perm.subsystem !== subsystem) {
              return false
            }
          }

          // 检查权限类型是否匹配
          return perm.parameterPer === permissionType
        })

        return matchedPermissions.length > 0
      } catch (err) {
        console.error('检查权限失败:', err)
        return false
      }
    },
    // 获取当前页面对应的 menuPath（根据 model 或其他信息判断）
    getMenuPath() {
      // 根据 model 或其他信息判断是玉柴还是竞品
      // 这里可以根据实际业务逻辑调整
      // 暂时返回通用的路径，或者根据实际需求调整
      return '玉柴发动机数据' // 或者 '竞品发动机数据'，需要根据实际情况判断
    },
    // 检查是否有查看权限（根据子系统）
    hasViewPermission(subsystem = null) {
      const menuPath = this.getMenuPath()
      return this.checkPermission(menuPath, subsystem, '查看')
    },
    // 检查是否有编辑权限（根据子系统）
    hasEditPermission(subsystem = null) {
      const menuPath = this.getMenuPath()
      return this.checkPermission(menuPath, subsystem, '编辑')
    },
    // 检查参数是否有编辑权限（根据parameterName匹配）
    hasParameterEditPermission(parameterName, subsystemName = null) {
      if (!parameterName) {
        return false
      }
      try {
        const permissionDataStr = localStorage.getItem('user_self_role')
        if (!permissionDataStr) {
          return false
        }
        const permissionData = JSON.parse(permissionDataStr)
        if (!Array.isArray(permissionData)) {
          return false
        }

        const menuPath = this.getMenuPath()

        // 查找匹配的权限：menuPath匹配，subsystem匹配（如果提供），parameterName匹配，且parameterPer为"编辑"
        const matchedPermissions = permissionData.filter((perm) => {
          // 检查 menuPath 是否匹配
          const menuMatch =
            perm.menuPath && (perm.menuPath.includes(menuPath) || menuPath.includes(perm.menuPath))
          if (!menuMatch) {
            return false
          }

          // 如果提供了 subsystemName，检查是否匹配
          if (subsystemName && perm.subsystem !== subsystemName) {
            return false
          }

          // 检查 parameterName 是否匹配
          if (perm.parameterName !== parameterName) {
            return false
          }

          // 检查权限类型是否为"编辑"
          return perm.parameterPer === '编辑'
        })
        return matchedPermissions.length > 0
      } catch (err) {
        console.error('检查参数权限失败:', err)
        return false
      }
    },
    // 检查是否有任意子系统的查看权限
    hasAnyViewPermission() {
      try {
        const permissionDataStr = localStorage.getItem('user_self_role')
        if (!permissionDataStr) {
          return false
        }
        const permissionData = JSON.parse(permissionDataStr)
        if (!Array.isArray(permissionData)) {
          return false
        }

        const menuPath = this.getMenuPath()

        // 检查是否有任意子系统的查看权限
        const matchedPermissions = permissionData.filter((perm) => {
          const menuMatch =
            perm.menuPath && (perm.menuPath.includes(menuPath) || menuPath.includes(perm.menuPath))
          return menuMatch && perm.parameterPer === '查看'
        })

        return matchedPermissions.length > 0
      } catch (err) {
        console.error('检查查看权限失败:', err)
        return false
      }
    },
    // 检查是否有任意子系统的编辑权限
    hasAnyEditPermission() {
      try {
        const permissionDataStr = localStorage.getItem('user_self_role')
        if (!permissionDataStr) {
          return false
        }
        const permissionData = JSON.parse(permissionDataStr)
        if (!Array.isArray(permissionData)) {
          return false
        }

        const menuPath = this.getMenuPath()

        // 检查是否有任意子系统的编辑权限
        const matchedPermissions = permissionData.filter((perm) => {
          const menuMatch =
            perm.menuPath && (perm.menuPath.includes(menuPath) || menuPath.includes(perm.menuPath))
          return menuMatch && perm.parameterPer === '编辑'
        })

        return matchedPermissions.length > 0
      } catch (err) {
        console.error('检查编辑权限失败:', err)
        return false
      }
    },
    // 加载责任人列表（从 GET_MANAGER_DATA 接口获取）
    loadResponsiblePersons() {
      const request = {
        ...api.GET_MANAGER_DATA,
        params: {
          pageNumber: 1,
          pageSize: 9999 // 获取所有数据
        },
        disableSuccessMsg: true
      }
      return this.$request(request)
        .asyncThen((resp) => {
          // 处理返回数据，支持不同的数据结构
          if (resp && resp.data) {
            const result = resp.data.result || []
            // 处理返回数据，转换为统一格式
            this.responsiblePersons = result.map((item) => ({
              id: item.userId || item.id, // 优先使用 userId
              userId: item.userId || item.userNumber || '',
              userNumber: item.userNumber || item.userId || '',
              userName: item.username || '',
              department: item.department || '',
              subsystem: item.subsystem || ''
            }))
          } else {
            this.responsiblePersons = []
          }
        })
        .asyncErrorCatch((err) => {
          console.error('加载责任人列表失败:', err)
          this.responsiblePersons = []
        })
    },
    // 加载填写人列表（从 GET_FILLER_DATA 接口获取）
    loadFillerPersons() {
      const request = {
        ...api.GET_FILLER_DATA,
        params: {
          pageNumber: 1,
          pageSize: 9999 // 获取所有数据
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          // 处理返回数据，支持不同的数据结构
          if (resp && resp.data) {
            const result = resp.data.result || []
            // 处理返回数据，转换为统一格式
            this.fillerPersons = result.map((item) => ({
              id: item.userId || item.userNumber || '', // 优先使用 userId
              userId: item.userId || item.userNumber || '',
              userNumber: item.userNumber || item.userId || '',
              userName: item.username || '',
              department: item.department || '',
              subsystem: item.subsystem || ''
            }))
          } else {
            this.fillerPersons = []
          }
        })
        .asyncErrorCatch((err) => {
          console.error('加载填写人列表失败:', err)
          this.fillerPersons = []
        })
    },
    // 根据部门和子系统过滤责任人列表
    getFilteredResponsiblePersons(department, subsystem) {
      if (!department && !subsystem) {
        return this.responsiblePersons
      }
      return this.responsiblePersons.filter((person) => {
        // 如果提供了部门，必须匹配
        if (department && person.department !== department) {
          return false
        }
        // 如果提供了子系统，必须匹配（subsystem 可能是逗号分隔的字符串）
        if (subsystem) {
          const personSubsystems = person.subsystem ? person.subsystem.split(',') : []
          if (!personSubsystems.includes(subsystem)) {
            return false
          }
        }
        return true
      })
    },
    // 根据部门和子系统过滤填写人列表（保留以兼容旧代码，但不再使用）
    getFilteredFillerPersons(department, subsystem) {
      if (!department && !subsystem) {
        return this.fillerPersons
      }
      return this.fillerPersons.filter((person) => {
        // 如果提供了部门，必须匹配
        if (department && person.department !== department) {
          return false
        }
        // 如果提供了子系统，必须匹配（subsystem 可能是逗号分隔的字符串）
        if (subsystem) {
          const personSubsystems = person.subsystem ? person.subsystem.split(',') : []
          if (!personSubsystems.includes(subsystem)) {
            return false
          }
        }
        return true
      })
    },
    // 获取填写人用户选项（用于远程搜索）
    getFillerUserOptions(row) {
      const rowId = row.id || `${row.subsystemName}-${row.parameterName}`
      return this.fillerUserOptions[rowId] || []
    },
    // 远程搜索填写人
    handleFillerRemoteSearch(query, row) {
      const rowId = row.id || `${row.subsystemName}-${row.parameterName}`

      // 如果查询为空，保留已选择的人员信息
      if (!query || query.trim() === '') {
        if (row.filledByUserId) {
          const selectedOptions = (this.fillerUserOptions[rowId] || []).filter(
            (opt) => opt.userId === row.filledByUserId
          )
          this.$set(this.fillerUserOptions, rowId, selectedOptions)
        } else {
          this.$set(this.fillerUserOptions, rowId, [])
        }
        return
      }

      this.fillerUserLoading = true
      const trimmedQuery = query.trim()
      const request = {
        ...api.GET_ALLUSERS,
        params: {
          name: trimmedQuery
        },
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          const respData = resp && resp.data
          let result = []
          if (Array.isArray(respData)) {
            result = respData
          } else if (respData && Array.isArray(respData.result)) {
            result = respData.result
          } else if (respData && respData.data && Array.isArray(respData.data)) {
            result = respData.data
          }
          // 转换为选项格式：{userId: user.userId, username: user.username, userNumber: user.userNumber}
          const users = result
            .map((user) => ({
              userId: user.userId || user.id,
              username: user.username || user.name,
              userNumber: user.userNumber || user.userId || user.id
            }))
            .filter((user) => user.userId && user.userNumber)

          // 获取已选择的 userId
          const selectedUserId = row.filledByUserId
          const selectedOptions = (this.fillerUserOptions[rowId] || []).filter(
            (opt) => opt.userId && opt.userId === selectedUserId
          )

          // 去重：使用 Map 确保每个 userNumber 只出现一次
          const optionsMap = new Map()
          // 先添加已选择的选项
          selectedOptions.forEach((opt) => {
            if (opt.userNumber) {
              optionsMap.set(opt.userNumber, opt)
            }
          })
          // 再添加新的搜索结果
          users.forEach((user) => {
            if (user.userNumber && !optionsMap.has(user.userNumber)) {
              optionsMap.set(user.userNumber, user)
            }
          })
          this.$set(this.fillerUserOptions, rowId, Array.from(optionsMap.values()))
          this.fillerUserLoading = false
        })
        .asyncErrorCatch((err) => {
          console.error('搜索填写人失败:', err)
          // 搜索失败时，保留已选择的人员信息
          if (row.filledByUserId) {
            const selectedOptions = (this.fillerUserOptions[rowId] || []).filter(
              (opt) => opt.userId === row.filledByUserId
            )
            this.$set(this.fillerUserOptions, rowId, selectedOptions)
          } else {
            this.$set(this.fillerUserOptions, rowId, [])
          }
          this.fillerUserLoading = false
        })
    },
    // 处理填写人选择变化
    handleFillerChange(selectedUserId, row) {
      // selectedUserId 是选中的 userId（因为 el-option 的 value 是 person.userId）
      // v-model 已经自动更新了 row.filledByUserId（存储的是 userId）
      // filledBy 字段也使用 userId（用于提交）
      if (selectedUserId) {
        // filledBy 字段存储 userId（用于提交）
        row.filledBy = selectedUserId
      } else {
        row.filledBy = ''
        row.filledByUserId = ''
      }
    },
    // 根据部门过滤人员列表（保留以兼容旧代码）
    getFilteredPersonsByDepartment(department) {
      if (!department) {
        return this.responsiblePersons
      }
      return this.responsiblePersons.filter((person) => person.department === department)
    },
    // 根据ID获取人员名称（从责任人列表或填写人列表中查找）
    getPersonNameById(id) {
      if (!id) {
        return ''
      }
      // 先从责任人列表中查找
      let person = this.responsiblePersons.find((p) => p.id === id)
      if (person) {
        return person.userName
      }
      // 如果没找到，从填写人列表中查找
      person = this.fillerPersons.find((p) => p.id === id)
      return person ? person.userName : ''
    },
    handleBack() {
      // 如果在审批模式下，取消审批而不是返回
      if (this.isApprovalMode) {
        this.handleApprovalCancel()
        return
      }
      console.log('handleBack called')
      this.$emit('back')
    },
    onVersionChange() {
      // 切换版本时，如果处于编辑模式，退出编辑模式并恢复原始数据
      if (this.isEditMode) {
        this.handleCancelEdit()
      }
    },
    onVersionStatusChange(row, idx, section) {
      // 处理版本状态变更
      console.log('Version changed:', row, idx, section)
    },
    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 && isParent === true），三级节点（parentLabel !== null && isParent === false）
      const isFirstLevel = nodeInfo.parentLabel === null
      const isSecondLevel = nodeInfo.parentLabel !== null && nodeInfo.isParent === true
      const isThirdLevel = nodeInfo.parentLabel !== null && nodeInfo.isParent === false
      if (this.treeSearchMode === 'subsystem') {
        // 搜索子系统：只针对二级菜单
        if (isSecondLevel) {
          // 二级节点：检查是否匹配
          if (nodeLabel.includes(searchValue)) {
            return true
          }
        } else if (isThirdLevel) {
          // 三级节点：如果父节点（二级节点）匹配，则显示
          // 查找父节点信息
          const parentNodeInfo = Object.values(this.nodeMap).find(
            (info) => info.label === nodeInfo.parentLabel && info.isParent === true
          )
          if (parentNodeInfo) {
            const parentLabel = (parentNodeInfo.label || '').toLowerCase()
            if (parentLabel.includes(searchValue)) {
              return true
            }
          }
        } else if (isFirstLevel) {
          // 一级节点：如果其下任何二级子节点匹配，则显示
          // 一级节点始终显示（因为需要显示其子节点）
          return true
        }
        return false
      } else {
        // 搜索零部件名称：只针对三级菜单
        if (isThirdLevel) {
          // 三级节点：检查是否匹配
          return nodeLabel.includes(searchValue)
        } else if (isSecondLevel) {
          // 二级节点：如果其下任何三级子节点匹配，则显示
          // 需要检查子节点是否匹配
          if (data.children && Array.isArray(data.children)) {
            return data.children.some((child) => {
              const childLabel = (child.label || '').toLowerCase()
              return childLabel.includes(searchValue)
            })
          }
        } else if (isFirstLevel) {
          // 一级节点：如果其下任何三级子节点匹配，则显示
          // 需要递归检查所有子节点
          const hasMatchingChild = (node) => {
            if (node.children && Array.isArray(node.children)) {
              return node.children.some((child) => {
                const childNodeInfo = this.nodeMap[child.id]
                if (childNodeInfo && childNodeInfo.parentLabel !== null && childNodeInfo.isParent === false) {
                  // 三级节点
                  const childLabel = (child.label || '').toLowerCase()
                  if (childLabel.includes(searchValue)) {
                    return true
                  }
                } else if (childNodeInfo && childNodeInfo.parentLabel !== null && childNodeInfo.isParent === true) {
                  // 二级节点，递归检查其子节点
                  return hasMatchingChild(child)
                }
                return false
              })
            }
            return false
          }
          return hasMatchingChild(data)
        }
        return false
      }
    },
    handleTreeCheck(data, checkedInfo) {
      // 更新选中的keys
      this.checkedKeys = checkedInfo.checkedKeys
      // 根据选中的节点加载详情数据
      this.loadEngineDetail()
    },
    // 判断节点是否允许拖动（只允许拖动第二级子系统节点）
    allowDrag(draggingNode) {
      const nodeInfo = this.nodeMap[draggingNode.data.id]
      if (!nodeInfo) {
        return false
      }
      // 只允许拖动第二级子系统节点（不是整车参数，不是第一级，不是第三级）
      // 第二级节点的特征：isParent 为 true，且不是整车参数
      return (
        nodeInfo.isParent &&
        !nodeInfo.isWholeEngineParams &&
        nodeInfo.parentLabel !== null // 有父节点，说明是第二级
      )
    },
    // 判断节点是否允许放置
    allowDrop(draggingNode, dropNode, type) {
      // 只允许在第二级之间拖放
      const draggingNodeInfo = this.nodeMap[draggingNode.data.id]
      const dropNodeInfo = this.nodeMap[dropNode.data.id]
      if (!draggingNodeInfo || !dropNodeInfo) {
        return false
      }
      // 拖动的节点必须是第二级子系统节点
      const isDraggingSecondLevel =
        draggingNodeInfo.isParent &&
        !draggingNodeInfo.isWholeEngineParams &&
        draggingNodeInfo.parentLabel !== null
      // 放置的节点也必须是第二级子系统节点（或第一级根节点）
      const isDropSecondLevel =
        dropNodeInfo.isParent &&
        !dropNodeInfo.isWholeEngineParams &&
        dropNodeInfo.parentLabel !== null
      const isDropRoot = dropNodeInfo.parentLabel === null && dropNodeInfo.isParent
      // 只允许在第二级之间拖放，或者拖放到根节点下
      if (type === 'prev' || type === 'next') {
        // 同级拖放：两个节点都必须是第二级
        return isDraggingSecondLevel && isDropSecondLevel
      } else if (type === 'inner') {
        // 拖放到内部：只能拖放到根节点下
        return isDraggingSecondLevel && isDropRoot
      }
      return false
    },
    // 处理节点拖拽完成
    handleNodeDrop(draggingNode, dropNode, dropType, ev) {
      // 找到第一级节点（根节点）
      const rootNode = this.treeData.find((node) => node.id === draggingNode.data.id || this.nodeMap[draggingNode.data.id]?.parentLabel === node.label)
      if (!rootNode) {
        // 如果找不到，使用第一个第一级节点
        if (this.treeData.length > 0) {
          const firstRootNode = this.treeData[0]
          this.handleSubsystemReorder(firstRootNode, draggingNode, dropNode, dropType)
        }
        return
      }
      this.handleSubsystemReorder(rootNode, draggingNode, dropNode, dropType)
    },
    // 处理子系统节点重新排序
    handleSubsystemReorder(rootNode, draggingNode, dropNode, dropType) {
      if (!rootNode || !rootNode.children) {
        return
      }
      // 获取根节点的所有子节点（包括"整车参数"和子系统）
      const rootChildren = rootNode.children || []
      // 找到"整车参数"节点，它应该始终在第一位
      const wholeEngineParamsNode = rootChildren.find(
        (node) => this.nodeMap[node.id] && this.nodeMap[node.id].isWholeEngineParams
      )
      // 找到所有子系统节点（排除"整车参数"）
      const subsystemNodes = rootChildren.filter(
        (node) => !this.nodeMap[node.id] || !this.nodeMap[node.id].isWholeEngineParams
      )
      // 重新排序子系统节点
      const draggingNodeId = draggingNode.data.id
      const dropNodeId = dropNode.data.id
      const draggingIndex = subsystemNodes.findIndex((node) => node.id === draggingNodeId)
      const dropIndex = subsystemNodes.findIndex((node) => node.id === dropNodeId)
      if (draggingIndex === -1 || dropIndex === -1) {
        return
      }
      // 从原位置移除
      const draggedNode = subsystemNodes.splice(draggingIndex, 1)[0]
      // 计算新的插入位置
      let newIndex = dropIndex
      if (dropType === 'prev') {
        // 拖放到目标节点之前
        newIndex = dropIndex
      } else if (dropType === 'next') {
        // 拖放到目标节点之后
        newIndex = dropIndex + 1
      } else if (dropType === 'inner') {
        // 拖放到目标节点内部（这种情况不应该发生，因为只允许同级拖放）
        newIndex = dropIndex
      }
      // 如果拖动节点在目标节点之后，需要调整索引
      if (draggingIndex < dropIndex) {
        newIndex = newIndex - 1
      }
      // 插入到新位置
      subsystemNodes.splice(newIndex, 0, draggedNode)
      // 重新组合：整车参数 + 排序后的子系统
      const newChildren = wholeEngineParamsNode
        ? [wholeEngineParamsNode, ...subsystemNodes]
        : subsystemNodes
      // 更新树数据
      rootNode.children = newChildren
      // 触发视图更新
      this.$forceUpdate()
    },
    shouldShowSection(sectionName) {
      // 如果选中了"整车参数"，不显示子系统参数
      if (this.isWholeEngineParamsSelected && !this.checkedKeys.some(nodeId => {
        const nodeInfo = this.nodeMap[nodeId]
        return nodeInfo && !nodeInfo.isWholeEngineParams && !nodeInfo.isParent
      })) {
        return false
      }
      // sectionName是参数类型（如"基本规格"），需要检查是否有对应的数据
      const data = this.versionData[this.currentVersionId] || {}
      if (!data[sectionName] || data[sectionName].length === 0) {
        return false
      }
      // 检查选中的节点中是否包含对应的零件名称
      // sectionName是零件名称，需要检查选中的子节点是否匹配
      // 如果选中了父节点，也应该显示其下所有零件名称的数据
      let hasMatch = false
      this.checkedKeys.forEach((nodeId) => {
        const nodeInfo = this.nodeMap[nodeId]
        if (nodeInfo) {
          // 跳过整机参数节点
          if (nodeInfo.isWholeEngineParams) {
            return
          }
          // 如果选中的是子节点，且label匹配零件名称
          if (!nodeInfo.isParent && nodeInfo.label === sectionName) {
            hasMatch = true
          }
          // 如果选中的是父节点，检查该section的数据是否属于该父节点
          if (nodeInfo.isParent) {
            const sectionData = data[sectionName] || []
            // 如果 sectionName 等于子系统名称，说明这是零部件名称为 "/" 的分组
            // 这种情况下，sectionName 就是子系统名称，所以直接匹配
            if (sectionName === nodeInfo.label) {
              hasMatch = true
            } else {
              // 否则检查该section的数据是否属于该父节点
              const hasDataInSubsystem = sectionData.some(
                (param) => param.subsystemName === nodeInfo.label
              )
              if (hasDataInSubsystem) {
                hasMatch = true
              }
            }
          }
        }
      })
      return hasMatch
    },
    handleEdit() {
      // 进入编辑模式，保存原始数据
      this.originalData = JSON.parse(JSON.stringify(this.versionData))
      // 保存编辑前的树节点状态
      this.savedCheckedKeys = [...this.checkedKeys]
      this.savedDefaultExpandedKeys = [...this.defaultExpandedKeys]
      this.changeData = [] // 重置修改数据数组

      // 确保参数值正确反显：如果 parameterValue 为空但 minorVersion 有值，则使用 minorVersion
      const currentData = this.versionData[this.currentVersionId] || {}
      Object.keys(currentData).forEach((partsName) => {
        const params = currentData[partsName] || []
        params.forEach((param) => {
          // 如果 parameterValue 为空或不存在，但 minorVersion 有值，则使用 minorVersion
          if ((!param.parameterValue || param.parameterValue === '') && param.minorVersion) {
            this.$set(param, 'parameterValue', param.minorVersion)
          }
        })
      })

      this.isEditMode = true
    },
    handleSaveEdit() {
      // 收集所有修改项
      this.changeData = []

      if (!this.originalData) {
        this.$message({
          type: 'warning',
          message: '没有原始数据，无法比较'
        })
        return
      }

      const currentData = this.versionData[this.currentVersionId] || {}
      const originalVersionData = this.originalData[this.currentVersionId] || {}

      // 遍历当前版本的所有零件名称
      Object.keys(currentData).forEach((partsName) => {
        const currentParams = currentData[partsName] || []
        const originalParams = originalVersionData[partsName] || []

        // 创建原始数据的映射，方便查找
        const originalMap = new Map()
        originalParams.forEach((param) => {
          const key = param.id || `${param.parameterName}_${param.subsystemName}`
          originalMap.set(key, param)
        })

        // 遍历当前参数，找出修改项
        currentParams.forEach((currentParam) => {
          const key =
            currentParam.id || `${currentParam.parameterName}_${currentParam.subsystemName}`
          const originalParam = originalMap.get(key)

          if (originalParam) {
            // 比较 parameterValue 是否有变化
            const currentValue = currentParam.parameterValue || ''
            const originalValue = originalParam.parameterValue || ''

            if (currentValue !== originalValue) {
              // 有修改，添加到 changeData
              this.changeData.push({
                id: currentParam.id,
                parameterId: currentParam.parameterId,
                engineModelId: currentParam.engineModelId,
                parameterValue: currentValue,
                operation: 'UPDATE',
                parameterName: currentParam.parameterName,
                partsName: currentParam.partsName,
                subsystemName: currentParam.subsystemName,
                department: currentParam.department,
                unit: currentParam.unit,
                majorVersion: currentParam.majorVersion,
                minorVersion: currentParam.minorVersion,
                versionStatus: currentParam.versionStatus
              })
            }
          } else {
            // 新添加的参数（虽然当前逻辑可能不会出现这种情况）
            this.changeData.push({
              id: currentParam.id,
              parameterId: currentParam.parameterId,
              engineModelId: currentParam.engineModelId,
              parameterValue: currentParam.parameterValue || '',
              parameterName: currentParam.parameterName,
              partsName: currentParam.partsName,
              subsystemName: currentParam.subsystemName,
              department: currentParam.department,
              unit: currentParam.unit,
              majorVersion: currentParam.majorVersion,
              minorVersion: currentParam.minorVersion,
              versionStatus: currentParam.versionStatus
            })
          }
        })
      })

      // 如果没有修改项，提示用户
      if (this.changeData.length === 0) {
        this.$message.info('没有数据被修改')
        this.isEditMode = false
        this.originalData = null
        return
      }

      console.log('修改的数据项:', this.changeData)
      for (const item of this.changeData) {
        item.operation = 'UPDATE'
      }
      const config = api.UPDATE_PARAM
      let requestUrl = config.url + getUserId()
      // 保存编辑
      const request = {
        ...config,
        url: requestUrl,
        params: this.changeData
      }
      this.$request(request)
        .asyncThen((resp) => {
          // 使用编辑前保存的树节点状态，用于重新加载后恢复
          const savedCheckedKeys = [...this.savedCheckedKeys]
          const savedDefaultExpandedKeys = [...this.savedDefaultExpandedKeys]

          this.isEditMode = false
          this.originalData = null
          this.changeData = [] // 清空修改数据

          // 重新加载数据
          this.loadEngineDetail()

          // 恢复树节点状态
          this.$nextTick(() => {
            this.checkedKeys = savedCheckedKeys
            this.defaultExpandedKeys = savedDefaultExpandedKeys
            // 恢复树的选中和展开状态
            if (this.$refs.paramTree) {
              this.$refs.paramTree.setCheckedKeys(savedCheckedKeys)
              // 通过更新 expandedKeys 数据属性来控制展开状态
              this.expandedKeys = [...savedDefaultExpandedKeys]
            }
          })
        })
        .asyncErrorCatch((err) => {
          console.error('保存失败:', err)
        })
    },
    handleCancelEdit() {
      // 取消编辑，恢复原始数据
      if (this.originalData) {
        this.versionData = JSON.parse(JSON.stringify(this.originalData))
      }
      this.isEditMode = false
      this.originalData = null
      this.changeData = [] // 清空修改数据
    },
    handleBatchModifyResponsible() {
      // 直接打开弹窗，弹窗内部会处理数据加载
      this.$refs.batchModifyResponsibleModal.showModal()
    },
    handleBatchModifyConfirm(change) {
      // change 格式: { subsystem: '子系统名称', department: '部门名称', oldResponsiblePersonId: '1', newResponsiblePersonId: '2', userId: 'userId', userNumber: 'userNumber' }
      if (!change) {
        return
      }

      // 如果是批量修改填写人，直接更新页面数据
      if (this.dispatchType === 'update_param') {
        const { subsystem, partsName, department, userId, userNumber, username } = change
        console.log(change, 'change', subsystem, partsName, department, userId, userNumber, username)
        // partsName 现在是数组
        if (!subsystem || !partsName || !Array.isArray(partsName) || partsName.length === 0 || !department || !userId) {
          this.$message({
            type: 'warning',
            message: '缺少必要参数'
          })
          return
        }

        // 获取当前版本的数据
        const currentData = this.versionData[this.currentVersionId] || {}
        let updateCount = 0

        // 构建填写人选项信息（用于填充 fillerUserOptions）
        // 如果 userNumber 为空，使用 userId 作为 userNumber（降级处理）
        const fillerOption = {
          userId: userId,
          username: username || '',
          userNumber: userNumber || userId
        }

        // 遍历所有零部件名称（partsName）
        Object.keys(currentData).forEach((dataPartsName) => {
          const params = currentData[dataPartsName] || []
          // 遍历该零部件下的所有参数
          params.forEach((param, index) => {
            // 获取参数的零部件名称（优先使用param.partsName，否则使用dataPartsName）
            const paramPartsName = param.partsName || dataPartsName

            // 检查参数是否匹配子系统、零部件名称（数组）和部门
            // 当 partsName 数组中包含 '/' 时，匹配所有子系统为选中子系统且 partsName 为 '/' 的参数
            // 当 partsName 数组中包含其他值时，匹配对应的零部件名称
            if (
              param.subsystemName === subsystem &&
              partsName.includes(paramPartsName) &&
              param.department === department
            ) {
              // 更新填写人信息
              param.filledBy = userId // 填写人ID（userId，用于提交）
              param.filledByUserId = userId // 填写人userId（用于 el-select 的 v-model）

              // 使用 Vue.set 确保响应式更新
              this.$set(currentData[dataPartsName], index, param)

              // 更新该行的填写人选项，确保选择框能正确显示
              const rowId = param.id || `${param.subsystemName}-${param.parameterName}`
              if (!this.fillerUserOptions[rowId]) {
                this.$set(this.fillerUserOptions, rowId, [])
              }
              // 检查是否已存在该填写人选项
              const existingOption = this.fillerUserOptions[rowId].find(
                opt => opt.userId === userId || opt.userNumber === userNumber
              )
              if (!existingOption) {
                // 如果不存在，添加到选项中
                this.fillerUserOptions[rowId].push(fillerOption)
              } else {
                // 如果已存在，更新信息
                existingOption.userId = userId
                existingOption.userNumber = userNumber || userId
                existingOption.username = username || existingOption.username || ''
              }

              updateCount++
            }
          })
        })

        // 强制更新视图，确保所有更改都能正确显示
        this.$nextTick(() => {
          this.$forceUpdate()
        })

        if (updateCount > 0) {
          // this.$message.success(`已批量更新 ${updateCount} 个参数的填写人`)
        } else {
          this.$message.warning('未找到匹配的参数')
        }
        return
      }

      // 批量修改责任人：重新加载责任人列表，确保数据是最新的
      this.loadResponsiblePersons().then(() => {
        // 责任人列表加载完成后，重新调用接口获取详情数据并重新渲染责任人
        // 保存当前的选中节点，以便重新加载后恢复
        const savedCheckedKeys = [...this.checkedKeys]
        // 重新加载详情数据，这会触发 processDetailData 重新渲染责任人
        this.loadEngineDetail()
        // 恢复选中状态
        this.$nextTick(() => {
          this.checkedKeys = savedCheckedKeys
          if (this.$refs.paramTree && savedCheckedKeys.length > 0) {
            this.$refs.paramTree.setCheckedKeys(savedCheckedKeys)
          }
        })
      })
    },
    handleConfirmDispatch() {
      const dispatchData = []
      const currentData = this.versionData[this.currentVersionId] || {}
      const isUpdateParamMode = this.dispatchType === 'update_param'

      // 遍历当前版本的所有零件名称
      Object.keys(currentData).forEach((partsName) => {
        const currentParams = currentData[partsName] || []

        // 遍历当前参数，检查是否有责任人或填写人，有值就直接分发（不管是否变化）
        currentParams.forEach((currentParam) => {
          let shouldDispatch = false
          let fieldValue = ''

          if (isUpdateParamMode) {
            // 分发填写人模式：检查是否有填写人
            fieldValue = currentParam.filledBy || ''
            if (fieldValue) {
              shouldDispatch = true
            }
          } else {
            // 分发责任人模式：检查是否有责任人
            fieldValue = currentParam.resPersonId || ''
            if (fieldValue) {
              shouldDispatch = true
            }
          }

          if (shouldDispatch) {
            // 有值，添加到分发数据
            const dataItem = {
              id: currentParam.id,
              parameterId: currentParam.parameterId,
              engineModelId: currentParam.engineModelId,
              parameterValue: currentParam.parameterValue || '',
              parameterName: currentParam.parameterName,
              partsName: currentParam.partsName,
              subsystemName: currentParam.subsystemName,
              department: currentParam.department,
              unit: currentParam.unit,
              majorVersion: currentParam.majorVersion,
              minorVersion: currentParam.minorVersion,
              versionStatus: currentParam.versionStatus,
              operation: 'UPDATE'
            }

            if (isUpdateParamMode) {
              // UPDATE_PARAM 接口需要 filledBy 字段
              dataItem.filledBy = fieldValue
            } else {
              // HANDLE_TODO_DISPATCH 或 HANDLE_RESPONSIBLE_DISPATCH 接口需要 resPersonId
              dataItem.resPersonId = fieldValue
              dataItem.filledBy = ''
            }

            dispatchData.push(dataItem)
          }
        })
      })

      if (dispatchData.length === 0) {
        const fieldName = isUpdateParamMode ? '填写人' : '责任人'
        this.$message({
          type: 'warning',
          message: `没有${fieldName}的数据需要分发`
        })
        return
      }

      // 根据分发类型调用不同的接口
      let apiConfig
      if (this.dispatchType === 'update_param') {
        // 分发填写人：调用 UPDATE_PARAM 接口
        apiConfig = api.HANDLE_RESPONSIBLE_DISPATCH
      } else if (this.dispatchType === 'responsible') {
        // 分发填写人：调用 HANDLE_RESPONSIBLE_DISPATCH 接口
        apiConfig = api.UPDATE_PARAM
      } else {
        // 分发责任人：调用 HANDLE_TODO_DISPATCH 接口
        apiConfig = api.HANDLE_TODO_DISPATCH
      }

      let requestUrl = apiConfig.url + getUserId()
      console.log(this.dispatchType, 'this.dispatchType', requestUrl, 111111)
      const request = {
        ...apiConfig,
        url: requestUrl,
        params: dispatchData,
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          this.$message({
            type: 'success',
            message: '分发成功'
          })
          // 返回路由上一级
          this.handleBack()
        })
        .asyncErrorCatch((err) => {
          console.error('分发失败:', err)
          this.$message({
            type: 'error',
            message: err.message || '分发失败'
          })
        })
    },
    // 加载机型详情信息
    loadEngineDetailInfo() {
      // if (!this.currentEngineModelID) {
      //   return
      // }
      // 这里可以根据实际接口获取机型详情信息
      // 暂时使用 props 中的 detail 或 model
      console.log(this.detail, 'this.detail', this.detail.id)
      const request = {
        ...api.GET_ENGINE_TABLE_DETAIL,
        params: {
          modelID: this.detail.id
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          if (resp && resp.data) {
            this.engineDetailInfo = resp.data
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取机型详情失败:', err)
          this.$message({
            type: 'error',
            message: '获取机型详情失败'
          })
        })
    },
    // 加载树数据
    loadTreeData() {
      if (!this.detail || !this.detail.id) {
        console.warn('缺少 detail.id，无法加载树数据')
        return
      }
      const request = {
        ...api.GET_ENGINE_TABLE_DETAIL,
        params: {
          modelID: this.detail.id
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          // 处理接口返回的数据
          if (resp && resp.data) {
            // 接口返回的是三级树结构：
            // { "第一级key": { "第二级子系统名": ["第三级参数名1", "第三级参数名2", ...] } }
            const data = resp.data
            // 保存"整车参数"的原始第三级数据
            this.saveWholeEngineParamsData(data)
            this.treeData = this.convertThreeLevelTree(data)
            // 设置默认展开：展开一级和二级节点，收起第三级节点
            const firstLevelKeys = this.getFirstLevelNodeKeys(this.treeData)
            const secondLevelKeys = this.getSecondLevelNodeKeys(this.treeData)
            // 合并一级和二级节点的keys
            const defaultExpandedKeysForFirstLoad = [...new Set([...firstLevelKeys, ...secondLevelKeys])]
            // 只有在首次加载（expandedKeys 为空）时才设置默认展开状态
            // 如果已经有展开状态（用户手动展开/收起了节点），保持当前状态不变
            const isFirstLoad = this.expandedKeys.length === 0
            if (isFirstLoad) {
              this.defaultExpandedKeys = defaultExpandedKeysForFirstLoad
              this.expandedKeys = [...defaultExpandedKeysForFirstLoad] // 初始化展开的keys（一级和二级）
            } else {
              // 如果已有展开状态，只更新 defaultExpandedKeys，保持 expandedKeys 不变
              this.defaultExpandedKeys = firstLevelKeys
              // 保持当前的 expandedKeys 不变，确保展开状态不被重置
            }
            // 设置默认选中：全选
            const allKeys = this.getAllNodeKeys(this.treeData)
            this.checkedKeys = allKeys
            // 使用 $nextTick 确保树组件渲染完成后再设置选中状态
            this.$nextTick(() => {
              // 使用 setCheckedKeys 方法设置全选状态
              if (this.$refs.paramTree && allKeys.length > 0) {
                this.$refs.paramTree.setCheckedKeys(allKeys)
              }
              // 确保树组件同步展开状态（保持当前的展开状态）
              // 只有在首次加载时才需要同步，否则保持用户手动设置的展开状态
              if (isFirstLoad) {
                this.$nextTick(() => {
                  if (this.$refs.paramTree && this.$refs.paramTree.store) {
                    const allNodes = this.$refs.paramTree.store._getAllNodes()
                    allNodes.forEach((node) => {
                      const shouldBeExpanded = this.expandedKeys.includes(node.id)
                      if (shouldBeExpanded && !node.expanded) {
                        node.expand()
                      } else if (!shouldBeExpanded && node.expanded) {
                        node.collapse()
                      }
                    })
                  }
                })
              }
              // 如果有 detail.id，加载详情数据（默认全选后自动加载）
              if (this.detail && this.detail.id && allKeys.length > 0) {
                this.loadEngineDetail()
              }
            })
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取参数列表失败:', err)
          this.$message({
            type: 'error',
            message: '获取参数列表失败'
          })
        })
    },
    // 保存"整车参数"的原始第三级数据
    saveWholeEngineParamsData(data) {
      this.wholeEngineParamsRawData = []
      // 遍历第一级数据
      Object.keys(data).forEach((firstLevelKey) => {
        const secondLevelData = data[firstLevelKey]
        if (typeof secondLevelData === 'object' && !Array.isArray(secondLevelData)) {
          // 查找"整车参数"的第三级数据
          if (secondLevelData['整车参数'] && Array.isArray(secondLevelData['整车参数'])) {
            // 保存"整车参数"的第三级数据（数组格式）
            this.wholeEngineParamsRawData = secondLevelData['整车参数'].filter(
              (paramName) => paramName && paramName !== '/'
            )
          }
        }
      })
    },
    // 将三级树结构转换为树形数据
    // 输入格式: { "第一级key": { "第二级子系统名": ["第三级参数名1", "第三级参数名2", ...] } }
    convertThreeLevelTree(data) {
      const treeData = []
      this.nodeMap = {} // 重置节点映射

      // 遍历第一级（接口返回的 key，如 "添加1+sdf"）
      Object.keys(data).forEach((firstLevelKey, firstIdx) => {
        const firstLevelId = `first-${firstIdx}`
        const firstLevelNode = {
          id: firstLevelId,
          label: firstLevelKey,
          tip: '',
          children: []
        }

        // 保存第一级节点映射
        this.nodeMap[firstLevelId] = {
          label: firstLevelKey,
          parentLabel: null,
          isParent: true
        }

        const secondLevelData = data[firstLevelKey]
        if (typeof secondLevelData === 'object' && !Array.isArray(secondLevelData)) {
          // 遍历第二级（子系统名称，如 "整车参数"、"起动子系统"）
          Object.keys(secondLevelData).forEach((subsystemName, secondIdx) => {
            const secondLevelId = `${firstLevelId}-${secondIdx}`
            const isWholeEngineParams = subsystemName === '整车参数'
            const thirdLevelParams = secondLevelData[subsystemName] || []
            const thirdLevelChildren = []

            // "整车参数"节点没有第三级，其他子系统有第三级
            if (!isWholeEngineParams) {
              // 遍历第三级（参数名称数组），进行去重
              if (Array.isArray(thirdLevelParams)) {
                // 使用 Set 进行去重，同时过滤掉 "/"
                const seenParams = new Set()
                thirdLevelParams.forEach((paramName, thirdIdx) => {
                  // 跳过空参数（"/"）和已存在的参数
                  if (paramName && paramName !== '/' && !seenParams.has(paramName)) {
                    seenParams.add(paramName)
                    const thirdLevelId = `${secondLevelId}-${thirdIdx}`
                    thirdLevelChildren.push({
                      id: thirdLevelId,
                      label: paramName,
                      tip: ''
                    })
                    // 保存第三级节点映射
                    this.nodeMap[thirdLevelId] = {
                      label: paramName,
                      parentLabel: subsystemName,
                      isParent: false
                    }
                  }
                })
              }
            }

            const secondLevelNode = {
              id: secondLevelId,
              label: subsystemName,
              tip: '',
              children: thirdLevelChildren
            }

            firstLevelNode.children.push(secondLevelNode)

            // 保存第二级节点映射
            this.nodeMap[secondLevelId] = {
              label: subsystemName,
              parentLabel: firstLevelKey,
              isParent: true,
              isWholeEngineParams: isWholeEngineParams // 标记"整车参数"节点
            }
          })
        }

        treeData.push(firstLevelNode)
      })

      return treeData
    },
    // 添加第一级（modelName-projectNumber）和第一个子级（整机参数）到树
    addRootLevelToTree(originalTreeData) {
      // 获取第一级的标签（modelName-projectNumber）
      const rootLabel = this.getRootLabel()
      // 创建第一级节点
      const rootId = 'root-level'
      const wholeEngineParamsId = 'whole-engine-params'
      // 创建"整机参数"子节点
      const wholeEngineParamsNode = {
        id: wholeEngineParamsId,
        label: '整机参数',
        tip: '',
        children: []
      }
      // 创建第一级节点，包含"整机参数"和原有的子系统数据
      const rootNode = {
        id: rootId,
        label: rootLabel,
        tip: '',
        children: [wholeEngineParamsNode, ...originalTreeData]
      }
      // 更新节点映射
      this.nodeMap[rootId] = {
        label: rootLabel,
        parentLabel: null,
        isParent: true
      }
      this.nodeMap[wholeEngineParamsId] = {
        label: '整机参数',
        parentLabel: rootLabel,
        isParent: false,
        isWholeEngineParams: true // 标记为整机参数节点
      }
      // 更新原有节点的 parentLabel
      originalTreeData.forEach(node => {
        const originalParentId = node.id
        if (this.nodeMap[originalParentId]) {
          this.nodeMap[originalParentId].parentLabel = rootLabel
        }
        // 递归更新子节点
        if (node.children && node.children.length > 0) {
          this.updateChildrenParentLabel(node.children, node.label)
        }
      })
      return [rootNode]
    },
    // 更新子节点的 parentLabel
    updateChildrenParentLabel(children, parentLabel) {
      children.forEach(child => {
        if (this.nodeMap[child.id]) {
          this.nodeMap[child.id].parentLabel = parentLabel
        }
        if (child.children && child.children.length > 0) {
          this.updateChildrenParentLabel(child.children, child.label)
        }
      })
    },
    // 获取第一级的标签（从树数据中获取）
    getRootLabel() {
      // 从树数据中获取第一级的标签
      if (this.treeData && this.treeData.length > 0) {
        return this.treeData[0].label || ''
      }
      // 如果没有树数据，尝试从 engineDetailInfo 获取
      if (this.engineDetailInfo) {
        const modelName = this.engineDetailInfo.modelName || ''
        const projectNumber = this.engineDetailInfo.projectNumber || ''
        if (modelName && projectNumber) {
          return `${modelName}-${projectNumber}`
        } else if (modelName) {
          return modelName
        }
      }
      // 如果没有详情信息，使用 model prop
      if (this.model) {
        return this.model
      }
      return '机型详情'
    },
    // 将对象格式转换为树形结构
    // 输入格式: { "父节点名": ["子节点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) => {
            // 如果该 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
    },
    // 获取所有一级节点的keys（parentLabel === null 的节点）
    getFirstLevelNodeKeys(nodes) {
      const keys = []
      nodes.forEach((node) => {
        const nodeInfo = this.nodeMap[node.id]
        if (nodeInfo && nodeInfo.parentLabel === null) {
          keys.push(node.id)
        }
      })
      return keys
    },
    // 获取所有二级节点的keys（parentLabel !== null && isParent === true 的节点）
    getSecondLevelNodeKeys(nodes) {
      const keys = []
      const traverse = (nodeList) => {
        nodeList.forEach((node) => {
          const nodeInfo = this.nodeMap[node.id]
          if (nodeInfo && nodeInfo.parentLabel !== null && nodeInfo.isParent === true) {
            keys.push(node.id)
          }
          if (node.children && node.children.length > 0) {
            traverse(node.children)
          }
        })
      }
      traverse(nodes)
      return keys
    },
    // 处理节点展开事件
    handleNodeExpand(data, node) {
      // 更新展开的keys
      if (!this.expandedKeys.includes(data.id)) {
        this.expandedKeys.push(data.id)
      }
    },
    // 处理节点收起事件
    handleNodeCollapse(data, node) {
      // 更新展开的keys
      const index = this.expandedKeys.indexOf(data.id)
      if (index > -1) {
        this.expandedKeys.splice(index, 1)
      }
    },
    // 一键展开所有二级节点
    handleExpandAllSecondLevel() {
      const firstLevelKeys = this.getFirstLevelNodeKeys(this.treeData)
      const secondLevelKeys = this.getSecondLevelNodeKeys(this.treeData)
      // 合并一级节点keys和二级节点keys
      const allExpandedKeys = [...new Set([...firstLevelKeys, ...secondLevelKeys])]
      // 更新展开状态（通过更新 expandedKeys 数据属性来控制）
      this.expandedKeys = [...allExpandedKeys]
      // 使用 $nextTick 确保视图更新，并使用 ref 调用 setExpandedKeys 方法
      this.$nextTick(() => {
        // 检查 $refs.paramTree 是否存在
        if (!this.$refs.paramTree) {
          console.warn('$refs.paramTree 不存在，无法展开节点')
          return
        }
        // 检查 setExpandedKeys 方法是否存在
        if (typeof this.$refs.paramTree.setExpandedKeys !== 'function') {
          console.warn('setExpandedKeys 方法不存在，尝试使用 store 方式')
          // 降级方案：使用 store 方式
          if (this.$refs.paramTree.store) {
            const allNodes = this.$refs.paramTree.store._getAllNodes()
            allNodes.forEach((node) => {
              const nodeInfo = this.nodeMap[node.id]
              if (nodeInfo) {
                // 如果是一级节点或二级节点，则展开
                if (nodeInfo.parentLabel === null || (nodeInfo.parentLabel !== null && nodeInfo.isParent === true)) {
                  if (allExpandedKeys.includes(node.id) && !node.expanded) {
                    node.expand()
                  }
                }
              }
            })
          }
        } else {
          // 使用 setExpandedKeys 方法
          this.$refs.paramTree.setExpandedKeys(allExpandedKeys)
        }
      })
    },
    // 一键收起所有二级节点
    handleCollapseAllSecondLevel() {
      // 只保留一级节点keys
      const firstLevelKeys = this.getFirstLevelNodeKeys(this.treeData)
      // 更新展开状态（通过更新 expandedKeys 数据属性来控制）
      this.expandedKeys = [...firstLevelKeys]
      // 使用 $nextTick 确保视图更新，并使用 ref 调用 setExpandedKeys 方法
      this.$nextTick(() => {
        // 检查 $refs.paramTree 是否存在
        if (!this.$refs.paramTree) {
          console.warn('$refs.paramTree 不存在，无法收起节点')
          return
        }
        // 检查 setExpandedKeys 方法是否存在
        if (typeof this.$refs.paramTree.setExpandedKeys !== 'function') {
          console.warn('setExpandedKeys 方法不存在，尝试使用 store 方式')
          // 降级方案：使用 store 方式
          if (this.$refs.paramTree.store) {
            const allNodes = this.$refs.paramTree.store._getAllNodes()
            allNodes.forEach((node) => {
              const nodeInfo = this.nodeMap[node.id]
              // 如果是二级节点（parentLabel !== null && isParent === true），则收起
              if (nodeInfo && nodeInfo.parentLabel !== null && nodeInfo.isParent === true) {
                if (node.expanded) {
                  node.collapse()
                }
              }
            })
          }
        } else {
          // 使用 setExpandedKeys 方法
          this.$refs.paramTree.setExpandedKeys(firstLevelKeys)
        }
      })
    },
    // 根据选中的树节点提取父级和子级
    getSelectedSubsystemsAndTypes() {
      const subsystemNames = []
      const parameterTypes = []
      const subsystemTypes = [] // 格式：["子系统名称-参数类型"]
      const processedSubsystems = new Set()
      const processedSubsystemTypes = new Set() // 用于去重

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

        // 排除第一级节点（parentLabel 为 null 的节点），不参与接口传参
        if (nodeInfo.parentLabel === null) {
          return
        }

        // 排除"整车参数"节点，不参与接口传参
        if (nodeInfo.isWholeEngineParams) {
          return
        }

        if (nodeInfo.isParent) {
          // 如果是父节点（第二级子系统节点），检查是否是"整车参数"
          // "整车参数"节点不参与接口传参
          if (nodeInfo.isWholeEngineParams) {
            return
          }
          // 添加到 subsystemNames
          if (!processedSubsystems.has(nodeInfo.label)) {
            subsystemNames.push(nodeInfo.label)
            processedSubsystems.add(nodeInfo.label)
          }
          // 如果选中的是二级节点，按照 "子系统名称-/" 的格式传参
          const subsystemTypeStr = `${nodeInfo.label}-/`
          if (!processedSubsystemTypes.has(subsystemTypeStr)) {
            subsystemTypes.push(subsystemTypeStr)
            processedSubsystemTypes.add(subsystemTypeStr)
          }
        } else {
          // 如果是第三级节点（参数名称），添加父级（子系统）和参数名称
          // 注意：第三级节点的 parentLabel 是子系统名称
          // 检查父级是否是"整车参数"
          if (nodeInfo.parentLabel === '整车参数') {
            return
          }
          if (nodeInfo.parentLabel && !processedSubsystems.has(nodeInfo.parentLabel)) {
            subsystemNames.push(nodeInfo.parentLabel)
            processedSubsystems.add(nodeInfo.parentLabel)
          }
          if (nodeInfo.label) {
            // 参数名称可能包含 ":" 分隔符（如 "状态代号:sdf"），需要提取参数名称部分
            let paramName = nodeInfo.label
            if (paramName.includes(':')) {
              paramName = paramName.split(':')[0]
            }
            parameterTypes.push(paramName)
            // 构建 subsystemTypes：格式为 "子系统名称-参数名称"
            if (nodeInfo.parentLabel) {
              const subsystemTypeStr = `${nodeInfo.parentLabel}-${paramName}`
              if (!processedSubsystemTypes.has(subsystemTypeStr)) {
                subsystemTypes.push(subsystemTypeStr)
                processedSubsystemTypes.add(subsystemTypeStr)
              }
            }
          }
        }
      })

      return { subsystemNames, parameterTypes, subsystemTypes }
    },
    handleExportTemplate() {
      // if (!this.detail.id) {
      //   this.$message.warning('缺少机型ID，无法导出模板')
      //   return
      // }

      // 构建请求配置，使用 $axios 直接请求以支持 blob 响应
      const requestConfig = {
        url: api.EXPORT_TEMPLATE.url,
        method: api.EXPORT_TEMPLATE.method,
        params: {
          engineModelID: this.detail.id
        },
        responseType: 'blob' // 设置响应类型为 blob
      }

      this.$axios(requestConfig)
        .then((response) => {
          const blobData = response.data
          if (!blobData) {
            this.$message.error('下载失败，文件内容为空')
            return
          }

          // 检查响应是否为 JSON（错误响应）
          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 = () => {
                try {
                  const errorData = JSON.parse(reader.result)
                  this.$message.error(errorData.message || '下载失败')
                } catch (e) {
                  this.$message.error('下载失败')
                }
              }
              reader.readAsText(blobData)
            } catch (err) {
              console.error('解析下载失败响应异常:', err)
              this.$message.error('下载失败')
            }
            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)
        })
        .catch((err) => {
          console.error('导出模板失败:', err)
          this.$message.error('导出模板失败')
        })
    },
    // 处理导入按钮点击
    handleImport() {
      if (this.importing) {
        return
      }
      // if (!this.currentEngineModelID) {
      //   this.$message.warning('缺少机型ID，无法导入')
      //   return
      // }
      // 触发文件选择
      this.$refs.fileInput.click()
    },
    // 处理文件选择变化
    handleFileChange(event) {
      const file = event.target.files && event.target.files[0]
      if (!file) {
        return
      }

      // 验证文件类型
      const fileExtension = file.name
        .split('.')
        .pop()
        .toLowerCase()
      if (!['xlsx', 'xls'].includes(fileExtension)) {
        this.$message({
          type: 'warning',
          message: '请选择 Excel 文件（.xlsx 或 .xls）'
        })
        // 清空文件选择
        event.target.value = ''
        return
      }

      // 开始上传
      this.uploadFile(file)
      // 清空文件选择，以便下次可以选择同一个文件
      event.target.value = ''
    },
    // 上传文件
    uploadFile(file) {
      const formData = new FormData()
      formData.append('file', file)
      formData.append('modelId', this.detail.id)

      const request = {
        ...api.IMPORT_ENGINE_MODEL,
        params: formData,
        disableSuccessMsg: true
      }

      this.importing = true
      this.$upload(request, null, false)
        .then((resp) => {
          console.log('导入成功:', resp)
          // 导入成功后重新加载详情数据
          this.loadEngineDetail()
        })
        .catch((err) => {
          console.error('导入失败:', err)
          this.$message({
            type: 'error',
            message: '导入失败，请稍后重试'
          })
        })
        .finally(() => {
          this.importing = false
        })
    },
    // 加载引擎详情数据
    loadEngineDetail() {
      // 优先使用 detail.id，如果没有则使用 currentEngineModelID
      const modelID = (this.detail && this.detail.id) || this.currentEngineModelID
      if (!modelID) {
        console.warn('缺少 engineModelID，无法加载详情')
        return
      }

      const {
        subsystemNames,
        parameterTypes,
        subsystemTypes
      } = this.getSelectedSubsystemsAndTypes()

      // 如果没有选中任何节点，不调用接口
      if (subsystemNames.length === 0 && parameterTypes.length === 0) {
        return
      }
      console.log(subsystemNames, parameterTypes, subsystemTypes)

      // 构建请求参数
      const params = {
        engineModelID: modelID,
        subsystemParts: subsystemTypes // 格式：["子系统名称-参数类型"]
      }

      // 根据模式传递不同的用户ID参数
      // 优先使用 props 传递的值，如果没有则使用当前用户ID
      const currentUserId = getUserId()
      if (this.dispatchType === 'update_param') {
        // 分发填写人模式：传递 responsiblePersonId
        // 如果从 todo 页面传递了 responsiblePersonId，使用传递的值，否则使用当前用户ID
        params.responsiblePersonId = this.responsiblePersonId || currentUserId
      } else if (!this.isDispatchMode && this.isEditMode) {
        // 填写内容的编辑页面：传递 filledById
        // 如果从 todo 页面传递了 filledBy，使用传递的值，否则使用当前用户ID
        params.filledById = this.filledBy || currentUserId
      } else if (this.filledBy) {
        // 如果是填写发动机参数值模式（从 todo 页面传递），传递 filledBy
        params.filledById = this.filledBy
      }

      // 如果是批量修改责任人的分发责任人页面，添加 isRes 参数
      if (this.isDispatchMode && this.dispatchType !== 'update_param') {
        params.isRes = 1
      }

      const request = {
        ...api.GET_ENGINE_DETAIL,
        params: params,
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          // 处理返回的详情数据
          console.log('接口返回数据:', resp)
          if (resp && resp.data) {
            console.log('准备处理的数据:', resp.data)
            // 如果处于分发模式且还没有保存原始数据，先保存原始数据（在自动赋值责任人之前）
            // 创建一个临时副本，用于保存未自动赋值责任人的原始数据
            let tempOriginalData = null
            if (this.isDispatchMode && !this.dispatchOriginalData) {
              // 先处理数据（但不自动赋值责任人），用于保存原始数据
              // 由于 processDetailData 会修改 versionData，我们需要先保存当前状态
              tempOriginalData = JSON.parse(JSON.stringify(this.versionData))
            }
            this.processDetailData(resp.data)
            // 如果处于分发模式且还没有保存原始数据，使用之前保存的原始数据（不包含自动赋值的责任人）
            if (this.isDispatchMode && !this.dispatchOriginalData && tempOriginalData) {
              this.$nextTick(() => {
                // 使用处理数据前的原始数据，这样自动赋值的责任人会被视为变更
                this.dispatchOriginalData = tempOriginalData
              })
            } else if (this.isDispatchMode && !this.dispatchOriginalData) {
              // 如果之前没有保存，则保存当前数据（此时已自动赋值责任人）
              this.$nextTick(() => {
                this.dispatchOriginalData = JSON.parse(JSON.stringify(this.versionData))
              })
            }
            // 移除展开状态同步逻辑，避免在选中节点时触发收起操作
            // 树组件的展开状态由用户手动控制，不应在接口返回后自动修改
          } else {
            console.warn('接口返回数据为空或格式不正确', resp)
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取引擎详情失败:', err)
          this.$message.error('获取引擎详情失败')
        })
    },
    // 处理详情数据，转换为格式
    // 返回数据结构: { "系统参数": [{ partsName: "基本规格", parameterName: "发动机排量", ... }] }
    // 对象的key是子系统名称（父节点），数组中的partsName是零件名称（子节点）
    processDetailData(data) {
      if (!data || typeof data !== 'object') {
        console.warn('processDetailData: 数据格式不正确', data)
        return
      }

      // 初始化当前版本的数据结构，使用 Vue.set 确保响应式
      if (!this.versionData[this.currentVersionId]) {
        this.$set(this.versionData, this.currentVersionId, {})
      }

      // 遍历返回的数据对象，key是子系统名称（父节点）
      Object.keys(data).forEach((subsystemName) => {
        const paramList = data[subsystemName]
        if (!Array.isArray(paramList)) {
          return
        }

        // 按partsName分组，如果partsName是/，则根据subsystemName分类
        paramList.forEach((item) => {
          const partsName = item.partsName || item.parameterType || '其他'
          const parameterName = item.parameterName || ''

          // 如果partsName是/，则使用subsystemName作为分组key，否则使用partsName
          const groupKey = partsName === '/' ? subsystemName : partsName

          // 如果该分组还没有数据，使用 Vue.set 初始化数组
          if (!this.versionData[this.currentVersionId][groupKey]) {
            this.$set(this.versionData[this.currentVersionId], groupKey, [])
          }

          // 检查是否已存在相同的参数（根据id或parameterName+subsystemName判断）
          const existingIndex = this.versionData[this.currentVersionId][groupKey].findIndex(
            (param) => {
              if (item.id && param.id) {
                return param.id === item.id
              }
              return param.parameterName === parameterName && param.subsystemName === subsystemName
            }
          )

          const resPersonId = item.resPersonId || item.responsiblePersonId || item.filledBy || ''
          const filledBy = item.filledBy || item.responsiblePersonId || ''
          // 处理 department 字段，将 · 替换为 -
          const department = (item.department || '平台部').replace(/·/g, '-')
          // 处理 filledByUserId：如果 filledBy 有值，直接使用 filledBy（userId）
          let filledByUserId = ''
          if (filledBy) {
            // filledByUserId 存储 userId（与 filledBy 保持一致）
            filledByUserId = filledBy
          }

          // 根据子系统和部门查找责任人（默认赋值）
          // 从 GET_MANAGER_DATA 的返回值中查找匹配的责任人
          let owner = item.owner || item.responsiblePerson || item.responsiblePersonName || ''
          let finalResPersonId = resPersonId

          // 从责任人列表中查找匹配的责任人（根据子系统和部门）
          if (this.responsiblePersons && this.responsiblePersons.length > 0) {
            const matchedPerson = this.responsiblePersons.find((person) => {
              // 检查子系统是否匹配：子系统必须完全一致
              let subsystemMatch = false
              if (subsystemName && person.subsystem) {
                // 如果责任人的 subsystem 是逗号分隔的字符串，检查是否包含参数的子系统
                const personSubsystems = person.subsystem.split(',').map(s => s.trim())
                subsystemMatch = personSubsystems.includes(subsystemName)
              } else if (!subsystemName && !person.subsystem) {
                // 如果都没有子系统，也算匹配
                subsystemMatch = true
              }

              // 检查部门是否匹配：参数的部门要包括在责任人的部门中（部门路径匹配）
              let departmentMatch = false
              if (department && person.department) {
                // 标准化部门路径（将 · 替换为 -）
                const normalizedParamDept = department.replace(/·/g, '-')
                const normalizedPersonDept = person.department.replace(/·/g, '-')
                // 参数的部门要包括在责任人的部门中（即责任人的部门是参数的部门的父路径或相同路径）
                // 例如：参数部门 "A-B-C"，责任人部门 "A-B-C-D" 或 "A-B-C" 都匹配
                // 但责任人部门 "A-B" 不匹配
                departmentMatch = normalizedPersonDept === normalizedParamDept || normalizedPersonDept.startsWith(normalizedParamDept + '-')
              } else if (!department && !person.department) {
                // 如果都没有部门，也算匹配
                departmentMatch = true
              }

              return subsystemMatch && departmentMatch
            })

            if (matchedPerson) {
              // 默认赋值：使用匹配到的责任人的 userId 和 userName
              owner = matchedPerson.userName || ''
              finalResPersonId = matchedPerson.userId || matchedPerson.id || ''
            }
          }

          const paramData = {
            parameterName: parameterName,
            partsName: partsName,
            parameterValue: item.parameterValue || item.value || '', // 如果接口返回中没有这个字段，默认为空
            unit: item.unit || '-',
            department: department,
            owner: owner,
            subsystemName: subsystemName,
            id: item.id,
            parameterId: item.parameterId,
            engineModelId: item.engineModelId,
            majorVersion: item.majorVersion,
            minorVersion: item.minorVersion,
            versionStatus: item.versionStatus,
            version: this.currentVersionId,
            resPersonId: finalResPersonId, // 责任人ID（使用 userId）
            filledBy: filledBy, // 填写人ID（userId，用于提交）
            filledByUserId: filledByUserId // 填写人userId（用于 el-select 的 v-model，与 filledBy 保持一致）
          }

          if (existingIndex >= 0) {
            // 如果已存在，使用 Vue.set 更新数据
            this.$set(
              this.versionData[this.currentVersionId][groupKey],
              existingIndex,
              paramData
            )
          } else {
            // 如果不存在，添加新数据
            this.versionData[this.currentVersionId][groupKey].push(paramData)
          }
        })
      })

      console.log('处理后的数据:', this.versionData[this.currentVersionId])
    },
    handleInitiateApproval() {
      // 切换到发起审批模式
      this.isApprovalMode = true
      // 重置表单数据
      this.approvalFormData = {
        processTitle: '',
        description: ''
      }
      // 重置变更数据
      this.approvalChangeData = []
      // 获取审批变更数据
      this.getApprovalChange()
      // 重置审批环节
      this.approvalWorkflowSteps = [
        {
          name: '校对',
          required: true,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '审核',
          required: true,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '会签',
          required: false,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '批准',
          required: true,
          handlers: [],
          options: [],
          loading: false
        }
      ]
    },
    getApprovalChange() {
      const request = {
        ...api.CHANGE_ENGINE_DATA,
        params: {
          modelID: this.detail.id,
          userID: getUserId()
        },
        disableSuccessMsg: true
      }
      this.$request(request)
        .asyncThen((resp) => {
          console.log('审批变更数据:', resp)
          if (resp && resp.data) {
            // 处理返回的数据，确保是数组格式
            if (Array.isArray(resp.data)) {
              this.approvalChangeData = resp.data
            } else if (resp.data.result && Array.isArray(resp.data.result)) {
              this.approvalChangeData = resp.data.result
            } else if (resp.data.data && Array.isArray(resp.data.data)) {
              this.approvalChangeData = resp.data.data
            } else {
              this.approvalChangeData = []
            }
          } else {
            this.approvalChangeData = []
          }
        })
        .asyncErrorCatch((err) => {
          console.error('获取审批变更失败:', err)
          this.approvalChangeData = []
          this.$message({
            type: 'error',
            message: '获取审批变更数据失败'
          })
        })
    },
    handleApprovalCancel() {
      // 取消审批，退出审批模式
      this.isApprovalMode = false
      // 重置表单数据
      this.approvalFormData = {
        processTitle: '',
        description: ''
      }
      // 重置变更数据
      this.approvalChangeData = []
      // 重置审批环节
      this.approvalWorkflowSteps = [
        {
          name: '校对',
          required: true,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '审核',
          required: true,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '会签',
          required: false,
          handlers: [],
          options: [],
          loading: false
        },
        {
          name: '批准',
          required: true,
          handlers: [],
          options: [],
          loading: false
        }
      ]
    },
    handleApprovalFormSubmit() {
      // 验证必填环节是否已选择处理人（会签不是必填）
      const requiredStepsWithoutHandlers = this.approvalWorkflowSteps.filter(
        (step) => step.required && (!step.handlers || step.handlers.length === 0)
      )
      if (requiredStepsWithoutHandlers.length > 0) {
        const stepNames = requiredStepsWithoutHandlers.map((step) => step.name).join('、')
        this.$message({
          type: 'warning',
          message: `请为必填环节"${stepNames}"选择处理人`
        })
        return
      }

      // 流程主题校验
      const processTitle = (this.approvalFormData.processTitle || '').trim()
      if (!processTitle) {
        this.$message.warning('请填写流程主题')
        return
      }

      // 构建 paramList：从当前版本数据中提取所有参数
      const paramList = []
      const currentData = this.versionData[this.currentVersionId] || {}
      console.log(this.currentEngineModelID, 'this.currentEngineModelID', this.currentData)
      Object.keys(currentData).forEach((partsNameKey) => {
        const params = currentData[partsNameKey] || []
        params.forEach((param) => {
          const paramItem = {
            id: param.id || '',
            parameterId: param.parameterId || '',
            engineModelId: param.engineModelId || this.currentEngineModelID,
            subsystemName: param.subsystemName || '',
            partsName: param.partsName || partsNameKey,
            parameterName: param.parameterName || '',
            parameterValue: param.parameterValue || '',
            responsiblePersonId: param.resPersonId || param.responsiblePersonId || '',
            department: param.department || '平台部',
            filledBy: param.filledBy || '',
            createdBy: getUserId(),
            majorVersion: param.majorVersion || 0,
            minorVersion: param.minorVersion || '',
            versionStatus: param.versionStatus || 0,
            approvalId: '',
            isDelete: '',
            beforeParamId: '',
            operation: param.operation || 'UPDATE',
            creationDate: '',
            lastUpdatedBy: '',
            lastUpdateDate: ''
          }
          paramList.push(paramItem)
        })
      })

      // 构建 nodeList：从审批环节中提取
      const nodeList = this.approvalWorkflowSteps.map((step, index) => ({
        nodeName: step.name,
        assignees: step.handlers,
        nodeOrder: index + 1
      }))

      // 构建提交数据
      const submitData = {
        modelId: this.detail.id,
        paramList: paramList,
        comment: this.approvalFormData.description,
        processTitle: processTitle,
        nodeList: nodeList,
        userId: getUserId()
      }

      // 调用发起审批接口
      const request = {
        ...api.START_ENGINE_CHECK,
        params: submitData
      }

      this.approvalSubmitting = true
      this.$request(request)
        .asyncThen((resp) => {
          console.log('审批提交成功')
          this.approvalSubmitting = false
          this.isApprovalMode = false
          this.handleBack()
        })
        .asyncErrorCatch((err) => {
          console.error('审批提交失败:', err)
          this.approvalSubmitting = false
        })
    },
    handleRemoteSearch(query, stepIndex) {
      const step = this.approvalWorkflowSteps[stepIndex]
      if (!query || query.trim() === '') {
        // 空查询时，只保留已选择的人员在选项中
        if (step.handlers && step.handlers.length > 0) {
          const selectedOptions = step.options.filter((opt) => step.handlers.includes(opt.userId))
          const missingIds = step.handlers.filter(
            (id) => !selectedOptions.some((opt) => opt.userId === id)
          )
          if (missingIds.length > 0) {
            step.options = selectedOptions
          } else {
            step.options = selectedOptions
          }
        } else {
          step.options = []
        }
        return
      }

      step.loading = true
      const trimmedQuery = query.trim()
      const request = {
        ...api.GET_ALLUSERS,
        params: {
          name: trimmedQuery
        },
        disableSuccessMsg: true
      }

      this.$request(request)
        .asyncThen((resp) => {
          const respData = resp && resp.data
          let result = []
          if (Array.isArray(respData)) {
            result = respData
          } else if (respData && Array.isArray(respData.result)) {
            result = respData.result
          } else if (respData && respData.data && Array.isArray(respData.data)) {
            result = respData.data
          }
          // 转换为选项格式：{userId: user.userId, username: user.username, userNumber: user.userNumber}
          const users = result
            .map((user) => ({
              userId: user.userId || user.id,
              username: user.username || user.name,
              userNumber: user.userNumber || user.userId || user.id
            }))
            .filter((user) => user.userId && user.userNumber) // 过滤掉没有 userId 或 userNumber 的数据
          // step.handlers 现在是 userId 数组（因为 el-option 的 value 是 userId）
          const existingIds = new Set(step.handlers || [])
          // 过滤掉已选择的人员
          const filteredUsers = users.filter((user) => !existingIds.has(user.userId))
          // 合并：已选择的人员信息（从现有 options 中获取）+ 新的搜索结果
          const selectedOptions = (step.options || []).filter(
            (opt) => opt.userId && step.handlers && step.handlers.includes(opt.userId)
          )
          // 去重：使用 Map 确保每个 userNumber 只出现一次（使用 userNumber 作为 key 确保唯一性）
          const optionsMap = new Map()
          // 先添加已选择的选项
          selectedOptions.forEach((opt) => {
            if (opt.userNumber) {
              optionsMap.set(opt.userNumber, opt)
            }
          })
          // 再添加新的搜索结果
          filteredUsers.forEach((user) => {
            if (user.userNumber && !optionsMap.has(user.userNumber)) {
              optionsMap.set(user.userNumber, user)
            }
          })
          step.options = Array.from(optionsMap.values())
          step.loading = false
        })
        .asyncErrorCatch((err) => {
          console.error('搜索人员失败:', err)
          // 搜索失败时，保留已选择的人员信息
          if (step.handlers && step.handlers.length > 0) {
            const selectedOptions = step.options.filter((opt) => step.handlers.includes(opt.userId))
            step.options = selectedOptions
          } else {
            step.options = []
          }
          step.loading = false
        })
    },
    handleHandlerChange(stepIndex, selectedIds) {
      // 处理人员选择变化
      // selectedIds 是选中的 id 数组，格式: ['id1', 'id2', ...]
      // v-model 已经自动更新了 step.handlers 为 id 数组
    },
    // 格式化部门显示：只显示最后一个节点
    formatDepartmentDisplay(department) {
      if (!department) {
        return '平台部'
      }
      // 将 · 替换为 -
      const normalizedDept = department.replace(/·/g, '-')
      // 按 - 分割
      const parts = normalizedDept.split('-').filter(part => part.trim() !== '')
      // 只显示最后一个节点
      if (parts.length > 0) {
        return parts[parts.length - 1]
      }
      // 否则显示全部
      return normalizedDept
    },
    // 格式化章节标题：如果有零部件名称，显示"子系统-零部件名称"，否则只显示子系统
    formatSectionTitle(sectionKey, sectionData) {
      if (!sectionData || !Array.isArray(sectionData) || sectionData.length === 0) {
        return sectionKey
      }
      // 从第一个数据项中获取子系统名称和零部件名称
      const firstItem = sectionData[0]
      const subsystemName = firstItem.subsystemName || ''
      const partsName = firstItem.partsName || ''
      // 如果零部件名称是 '/' 或空，说明没有零部件名称，只显示子系统
      if (!partsName || partsName === '/') {
        return subsystemName || sectionKey
      }
      // 如果有零部件名称，显示"子系统-零部件名称"
      return `${subsystemName}-${partsName}`
    }
  }
}
</script>

<style lang="scss">
.engine-detail-page {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;

  .page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 56px;
    position: relative;
    width: 100%;
    min-height: 56px;
    background: #fff;
    border-bottom: 1px solid #ebeef5;
    padding: 0 20px;

    .header-left {
      display: flex;
      align-items: center;
      gap: 12px;
      flex: 1;
      .label {
        width: 50px !important;
      }
      .back-button {
        padding: 0;
        font-size: 14px;
        color: #409eff;
        cursor: pointer;
        pointer-events: auto;

        &:hover {
          color: #66b1ff;
        }

        i {
          margin-right: 4px;
        }
      }

      .title {
        color: #303133;
        font-weight: 700;
        margin: 0;
        font-size: 18px;
      }
    }

    .operation {
      display: flex;
      align-items: center;
      gap: 8px;
    }
  }

  .detail-body {
    display: flex;
    padding: 16px 20px 24px 20px;
    flex: 1;
    min-height: 0;
    overflow: hidden !important;
  }

  .page-approval-content {
    display: flex;
    flex: 1;
    min-height: 0;
    padding: 20px;
    overflow-y: auto;
    overflow-x: hidden;
  }

  .page-footer {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 16px 20px;
    background: #fff;
    border-top: 1px solid #ebeef5;
    flex-shrink: 0;
    position: relative;
    z-index: 10;

    .footer-buttons {
      display: flex;
      gap: 12px;
    }
  }

  .left-tree-panel {
    width: 200px;
    background: #fff;
    border: 1px solid #ebeef5;
    padding: 12px;
    font-size: 14px;
    overflow-y: auto !important;
    .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;
    }
    .tree-actions {
      display: flex;
      gap: 8px;
      margin-bottom: 8px;
      .el-button {
        flex: 1;
        padding: 5px 8px;
        font-size: 12px;
      }
    }
    .custom-tree-node {
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }
    .red-tip {
      color: #f56c6c;
      white-space: pre-line;
    }
  }

  .right-content {
    flex: 1;
    background: #fff;
    padding: 20px;
    margin-left: 20px;
    overflow-y: auto !important;
  }

  .section {
    margin-bottom: 24px;
    background: #fff;
  }

  .section-title {
    font-weight: 700;
    font-size: 16px;
    color: #303133;
    margin: 0 0 16px 0;
    padding: 0;
  }

  .grid {
    border: 1px solid #ebeef5;
    border-radius: 0;
  }

  .grid-header {
    display: grid;
    grid-template-columns: 1fr 100px 120px 200px 120px;
    background: #f5f7fa;
    border-bottom: 1px solid #ebeef5;

    &.edit-mode {
      grid-template-columns: 1fr 100px 1fr;
    }
  }

  .grid-row {
    display: grid;
    grid-template-columns: 1fr 100px 120px 200px 120px;
    border-bottom: 1px solid #ebeef5;
    background: #fff;

    &.edit-mode {
      grid-template-columns: 1fr 100px 1fr;
    }
  }

  // 整车参数表格样式（只有3列：参数名称、单位、参数值）
  .whole-engine-grid {
    .whole-engine-header {
      grid-template-columns: 1fr 100px 1fr;
    }

    .whole-engine-row {
      grid-template-columns: 1fr 100px 1fr;
    }
  }

  .grid-row:last-child {
    border-bottom: none;
  }

  .cell {
    padding: 12px 16px;
    border-right: 1px solid #ebeef5;
    font-size: 14px;
    color: #303133;
    text-align: left;
    display: flex;
    align-items: center;
  }

  .cell:last-child {
    border-right: none;
  }

  .header-cell {
    background: #f5f7fa;
    color: #606266;
    font-weight: normal;
    font-size: 14px;
  }

  .cell {
    ::v-deep .el-select:not(.responsible-select) {
      width: 100%;

      .el-input__inner {
        border: none;
        padding: 0;
        background: transparent;
        text-align: left;
        height: auto;
        line-height: normal;
      }

      .el-input__suffix {
        right: 0;
      }
    }

    .param-input {
      width: 100%;

      ::v-deep .el-input__inner {
        height: 32px;
        line-height: 32px;
        border: 1px solid #dcdfe6;
        border-radius: 4px;

        &:focus {
          border-color: #409eff;
        }
      }
    }

    .responsible-select {
      width: 100%;

      ::v-deep .el-input__inner {
        height: 32px !important;
        line-height: 32px !important;
        border: 1px solid #dcdfe6 !important;
        border-radius: 4px !important;
        background: #fff !important;
        padding: 0 30px 0 15px !important;

        &:focus {
          border-color: #409eff !important;
        }
      }
    }
  }

  .header-item {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-right: 16px;

    .label {
      color: #303133;
      width: 40px !important;
      font-size: 14px;
    }

    .value {
      color: #303133;
      font-size: 14px;
      font-weight: 500;
    }
  }

  .approval-content {
    display: flex;
    flex-direction: column;
    gap: 20px;
    width: 100%;

    .approval-change-table {
      display: flex;
      flex-direction: column;
      gap: 12px;

      .change-table-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
      }

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

        .change-table-content {
          width: 100%;
          border-collapse: collapse;
          border: 1px solid #ebeef5;
          background: #fff;

          thead {
            display: table;
            width: 100%;
            table-layout: fixed;
            background: #f5f7fa;

            th {
              padding: 12px 16px;
              text-align: left;
              font-size: 14px;
              font-weight: 600;
              color: #303133;
              border-bottom: 1px solid #ebeef5;
              border-right: 1px solid #ebeef5;
              white-space: nowrap;

              &:last-child {
                border-right: none;
              }

              &.col-engine-model-name {
                min-width: 120px;
              }

              &.col-subsystem-name {
                min-width: 150px;
              }

              &.col-parameter-type {
                min-width: 120px;
              }

              &.col-parts-name {
                min-width: 100px;
              }

              &.col-parameter-name {
                min-width: 180px;
              }

              &.col-parameter-value {
                min-width: 120px;
              }

              &.col-common {
                min-width: 200px;
              }
            }
          }

          tbody {
            display: block;
            max-height: 450px;
            overflow-y: auto;
            overflow-x: hidden;

            .change-table-row {
              display: table;
              width: 100%;
              table-layout: fixed;

              &:not(:last-child) {
                border-bottom: 1px solid #ebeef5;
              }

              &:hover {
                background: #f5f7fa;
              }

              td {
                padding: 12px 16px;
                font-size: 14px;
                color: #606266;
                border-right: 1px solid #ebeef5;
                vertical-align: middle;

                &:last-child {
                  border-right: none;
                }

                &.col-common {
                  color: #f56c6c;
                }
              }
            }
          }
        }
      }
    }

    .approval-description {
      display: flex;
      flex-direction: column;
      gap: 8px;
      margin-top: 10px;

      .description-label {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
      }
    }

    .approval-workflow {
      display: flex;
      flex-direction: column;
      gap: 16px;

      .workflow-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 8px;
      }

      .workflow-table {
        width: 100%;

        .workflow-table-content {
          width: 100%;
          border-collapse: collapse;
          border: 1px solid #ebeef5;

          thead {
            background: #f5f7fa;

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

              &.step-name-col {
                width: 120px;
              }

              &.handler-col {
                width: auto;
              }
            }
          }

          tbody {
            .workflow-row {
              &:not(:last-child) {
                border-bottom: 1px solid #ebeef5;
              }

              .step-name-cell {
                padding: 12px 16px;
                vertical-align: middle;

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

                  .required-mark {
                    color: #f56c6c;
                    margin-left: 4px;
                  }
                }
              }

              .handler-cell {
                padding: 12px 16px;
                vertical-align: middle;

                .handler-select {
                  width: 100%;
                  min-width: 200px;

                  ::v-deep .el-input__inner {
                    height: 32px;
                    line-height: 32px;
                  }

                  ::v-deep .el-tag {
                    margin: 2px 4px 2px 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
.el-select-dropdown__item {
  display: flex !important;
  justify-content: space-between !important;
  padding-right: 20px !important;
}
.username-text {
  color: #303133 !important;
  display: inline-block;
  text-align: right !important;
}
.user-id-text {
  color: #909399 !important;
  display: inline-block;
  margin-left: 20px;
  text-align: right !important;
}
.whole-engine-params-section {
  margin-bottom: 24px;
  background: #fff;
  .section-title {
    font-weight: 700;
    font-size: 16px;
    color: #303133;
    margin: 0 0 16px 0;
    padding: 0;
  }
  .whole-engine-params-table {
    border: 1px solid #ebeef5;
    border-radius: 0;
    overflow-x: auto;
    .whole-engine-table {
      width: 100%;
      border-collapse: collapse;
      thead {
        background: #f5f7fa;
        th {
          padding: 12px 16px;
          text-align: left;
          font-size: 14px;
          font-weight: 600;
          color: #303133;
          border-bottom: 1px solid #ebeef5;
          border-right: 1px solid #ebeef5;
          white-space: nowrap;
          &:last-child {
            border-right: none;
          }
        }
      }
      tbody {
        tr {
          border-bottom: 1px solid #ebeef5;
          background: #fff;
          &:hover {
            background: #f5f7fa;
          }
          &:last-child {
            border-bottom: none;
          }
          td {
            padding: 12px 16px;
            font-size: 14px;
            color: #606266;
            border-right: 1px solid #ebeef5;
            vertical-align: middle;
            &:last-child {
              border-right: none;
            }
          }
        }
      }
    }
  }
  .status-tag {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 2px;
    font-size: 12px;
    line-height: 1.5;
    &.status-done {
      background: #67c23a;
      color: white;
    }
    &.status-partial {
      background: #e6a23c;
      color: white;
    }
    &.status-pending {
      background: #f5f7fa;
      color: #606266;
    }
  }
}
</style>
