<template>
  <!-- <el-button @click="GetProjectStatus">测试</el-button> -->
  <div class="container">
    <!-- 复制面板对话框 -->
    <el-dialog v-model="showCopyPanelDialog" title="复制面板" width="400px" :close-on-click-modal="false">
      <el-select v-model="selectedCopyProjectId" placeholder="请选择项目" filterable clearable size="small"
        style="width: 100%; margin-bottom: 20px" @change="handleCopyProjectChange" :close-on-press-escape="false">
        <el-option v-for="project in projectList" :key="project.id" :label="project.hotel_name" :value="project.id" />
      </el-select>
      <template #footer>
        <div class="dialog-footer">
          <el-button size="small" @click="showCopyPanelDialog = false">取消</el-button>
          <el-button type="primary" size="small" @click="confirmCopyPanel">确认</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 生成项目总览图参数对话框 -->
    <el-dialog v-model="showProjectCdrDialog" title="生成项目总览图" width="520px" :close-on-click-modal="false"
      :close-on-press-escape="false">
      <el-form :model="projectCdrForm" label-width="90px" size="small">
        <el-form-item label="项目名称">
          <el-input v-model="projectCdrProjectName" disabled />
        </el-form-item>
        <el-form-item label="协议">
          <el-select v-model="projectCdrForm.Protocol" placeholder="请选择/输入协议" filterable allow-create
            default-first-option style="width: 100%">
            <el-option v-for="p in projectCdrEnums.protocols" :key="p" :label="p" :value="p" />
          </el-select>
        </el-form-item>
        <el-form-item label="开关系列">
          <el-select v-model="projectCdrForm.SwitchSeries" placeholder="请选择/输入开关系列" filterable allow-create
            default-first-option style="width: 100%">
            <el-option v-for="s in projectCdrEnums.switchSeries" :key="s" :label="s" :value="s" />
          </el-select>
        </el-form-item>
        <el-form-item label="插座系列">
          <el-select v-model="projectCdrForm.SocketSeries" placeholder="请选择插座系列" style="width: 100%">
            <el-option v-for="s in projectCdrEnums.socketSeries" :key="s" :label="s" :value="s" />
          </el-select>
        </el-form-item>
        <el-form-item label="中文字体">
          <el-select v-model="projectCdrForm.ChineseFont" placeholder="请选择/输入中文字体" filterable allow-create
            default-first-option style="width: 100%">
            <el-option v-for="font in fontList" :key="font.ID" :label="font.FontName" :value="font.FontName" />
          </el-select>
        </el-form-item>
        <el-form-item label="中文字号">
          <el-input-number v-model="projectCdrForm.ChineseFontSize" :min="0" :max="200" :step="0.1" :precision="1"
            controls-position="right" style="width: 40%" />
        </el-form-item>
        <el-form-item label="英文字体">
          <el-select v-model="projectCdrForm.EnglishFont" placeholder="请选择/输入英文字体" filterable allow-create
            default-first-option style="width: 100%">
            <el-option v-for="font in fontList" :key="font.ID" :label="font.FontName" :value="font.FontName" />
          </el-select>
        </el-form-item>
        <el-form-item label="英文字号">
          <el-input-number v-model="projectCdrForm.EnglishFontSize" :min="0" :max="200" :step="0.1" :precision="1"
            controls-position="right" style="width: 40%" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button size="small" @click="showProjectCdrDialog = false">取消</el-button>
          <el-button type="primary" size="small" @click="confirmProjectCdr">确认生成</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 左侧区域 -->
    <div class="left-panel">
      <div class="left-top">
        <span style="font-weight: bold">项目：</span>
        <el-select ref="projectSelect" v-model="selectedProjectId" placeholder="请选择项目" filterable clearable size="small"
          @change="handleProjectSelectorChange" @visible-change="onSelectVisibleChange" style="width: 40%; margin: 0px"
          :disabled="isProjectLocked">
          <el-option v-for="project in projectList" :key="project.id" :label="project.hotel_name" :value="project.id" />
        </el-select>
        <span style="margin-left: 2px;">
          <el-tooltip content="生成项目总览CDR图纸" placement="top">
            <el-button size="small" type="success" @click="GetAllProjectCDR" :disabled="!selectedProjectId || isProjectGenerating"
              style="width:18%;">
              生成项目总览
            </el-button>
          </el-tooltip>
          <el-tooltip content="下载项目CDR文件和雕刻文件" placement="top">
            <el-button size="small" type="warning" @click="DownloadProjectCDR" :disabled="!selectedProjectId || !isProjectDownloadAvailable"
              style="width:18%;">
              下载项目文件
            </el-button>
          </el-tooltip>
        </span>
      </div>
      <div class="left-bottom">
        <div class="left-bottom-top">
          <el-tree ref="projectTree" :data="treeData" node-key="id" :props="treeProps" :expand-on-click-node="true"
            default-expand-all @node-click="handleNodeClick" class="full-height-tree">
            <template #default="{ node, data }">
              <div class="tree-node-container">
                <span class="tree-node-label">
                  <span v-if="data.type === 'panel'">
                    <span v-if="
                      data.panelInfo &&
                      data.panelInfo.design_status == '生成中'
                    " style="font-size: 10px; color: #e6a23c">生成中</span>
                    <span v-else-if="
                      data.panelInfo && data.panelInfo.thumbnail_large && data.panelInfo.cdr_filename && data.panelInfo.carving_filename
                    " style="font-size: 10px; color: #67c23a">已生成</span>
                    <span v-else-if="
                      data.panelInfo && data.panelInfo.panel_info_json
                    " style="font-size: 10px; color: #909399">编辑中</span>
                    <span v-else style="font-size: 10px; color: #909399">待配置</span>
                  </span>
                  {{ node.label }}
                </span>
                <div class="tree-node-actions">
                  <!-- 项目节点 -->
                  <template v-if="data.type === 'project'">
                    <el-button size="small" link type="success" @click.stop="addRoomType(data)">新增房型</el-button>
                    <el-button size="small" link type="primary">&emsp;&emsp;</el-button>
                    <el-button v-if="data.project.report_id !== '1'" size="small" link type="danger"
                      @click.stop="removeProjectNode(data)">移除</el-button>
                    <el-popover placement="bottom-end" :width="880" trigger="click">
                      <template #reference>
                        <el-button size="small" class="detail-btn" link type="info"
                          v-if="data.project.id !== 1">详情</el-button>
                      </template>
                      <el-descriptions border column="2" size="small" class="details">
                        <el-descriptions-item label="项目名称">{{
                          data.project.hotel_name
                          }}</el-descriptions-item>
                        <!-- <el-descriptions-item label="详细地址">{{
                          data.project.addressDetail
                        }}</el-descriptions-item>
                        <el-descriptions-item label="所在地区">{{ data.project.quyu }} ·
                          {{ data.project.shengfen }}</el-descriptions-item> -->
                        <el-descriptions-item label="项目编号">{{
                          data.project.report_id
                          }}</el-descriptions-item>
                        <el-descriptions-item label="审批状态">
                          <el-tag size="small" :type="data.project.shengpiStatus === '3'
                            ? 'success'
                            : 'warning'
                            ">
                            已通过
                            <!-- {{
                              data.project.shengpiStatus === "3"
                                ? "已批准"
                                : "待审批"
                            }} -->
                          </el-tag>
                        </el-descriptions-item>
                        <el-descriptions-item label="报备信息">{{
                          data.project.remarks
                          }}</el-descriptions-item>
                        <!-- <el-descriptions-item label="房间信息">{{ data.project.roomTypeCount }} 种房型 ·
                          {{
                            data.project.roomTotalCount
                          }}
                          间客房</el-descriptions-item> -->
                        <!-- <el-descriptions-item label="最后更新">{{
                          formatDate(data.project.updatetime)
                        }}</el-descriptions-item> -->
                      </el-descriptions>
                    </el-popover>
                  </template>

                  <!-- 房型节点 -->
                  <template v-else-if="data.type === 'room'">
                    <el-button size="small" link type="success" @click.stop="addPanel(data)">新增面板组</el-button>
                    <el-button size="small" link type="primary" @click.stop="editRoomName(data)">修改</el-button>
                    <el-button size="small" link type="danger" @click.stop="deleteRoom(data)">删除</el-button>
                  </template>

                  <!-- 面板组节点 -->
                  <template v-else-if="data.type === 'panel'">
                    <el-button size="small" link type="primary" @click.stop="editPanelName(data)">修改</el-button>
                    <el-button size="small" link type="danger" @click.stop="deletePanel(data)">删除</el-button>
                  </template>
                </div>
              </div>
            </template>
          </el-tree>
        </div>

        <div class="left-bottom-bottom">
          <div class="section-header">
            <span>面板单元列表</span>
            <el-button size="small" type="info" @click="showAddPanelUnitDialogView" plain
              :disabled="!selectedProjectId">
              添加面板单元
            </el-button>
          </div>
          <div class="table-content">
            <el-table :data="unitTableData" height="100%" style="width: 100%" size="small"
              @row-click="handleUnitRowClick">
              <el-table-column label="状态" width="60" align="center" show-overflow-tooltip>
                <template #default="{ row }">
                  <span>
                    <span v-if="row && row.design_status == '生成中'" style="color: #e6a23c">生成中</span>
                    <span v-else-if="row && row.thumbnail_large" style="color: #67c23a">已生成</span>
                    <span v-else-if="row && row.elements_json" style="color: #909399">编辑中</span>
                    <span v-else style="font-size: 10px; color: #909399">待配置</span>
                  </span>
                </template>
              </el-table-column>
              <el-table-column prop="panel_name" label="面板单元名称" min-width="130" show-overflow-tooltip />
              <el-table-column label="操作" width="180" align="center">
                <template #default="{ row }">
                  <el-button size="small" link :type="currentPanelUnit === row.guid ? 'info' : 'primary'"
                    @click.stop="editPanelUnit(row)">
                    {{ currentPanelUnit === row.guid ? "编辑中" : "编辑" }}
                  </el-button>
                  <el-button size="small" link type="danger" @click.stop="deletePanelUnit(row)">
                    删除
                  </el-button>
                  <el-button size="small" link type="success" @click.stop="copyPanelUnit(row)">
                    复制面板
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>

        <div class="left-bottom-dynamic-list">
          <div class="section-header">
            <span>生成记录</span>
          </div>
          <div class="table-content">
            <el-table :data="generationHistory" style="width: 100%; height: 100%" size="small">
              <el-table-column prop="name" label="项目" min-width="90" show-overflow-tooltip />
              <el-table-column prop="type" label="类型" min-width="55" align="center" />
              <el-table-column prop="status" label="状态" min-width="60" align="center">
                <template #default="{ row }">
                  <el-tag :type="row.status === GenerationStatus.IN_PROGRESS
                    ? 'warning'
                    : row.status === GenerationStatus.COMPLETED
                      ? 'success'
                      : 'danger'
                    ">
                    {{ row.status }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="progress" label="进度" min-width="90" align="center">
                <template #default="{ row }">
                  <el-progress :percentage="row.progress" :show-text="true" size="small" />
                </template>
              </el-table-column>
              <el-table-column prop="duration" label="总耗时" min-width="50" align="center">
                <template #default="{ row }">
                  {{ row.duration !== null ? row.duration + "秒" : "-" }}
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>
      </div>
    </div>

    <!-- 右侧区域 -->
    <div class="right-panel">
      <!-- 面板组合配置 -->
      <div class="right-middle">
        <div class="panel-unit-config-container">
          <!-- 左边预览图区域 -->
          <div class="preview-section-top">
            <div class="section-header">
              <span>面板组预览图{{
                currentPanelNode?.panelInfo?.design_status === "生成中"
                  ? "（生成中）"
                  : ""
              }}</span>
              <div>
                <el-tooltip content="刷新面板组预览图" placement="top">
                  <el-button size="small" type="info" @click="refreshPanelGroupPreview" :disabled="!currentPanelNode">
                    刷新预览
                  </el-button>
                </el-tooltip>
              </div>
            </div>
            <div class="preview-content">
              <div v-if="panelGroupPreview" class="preview-image">
                <el-image style="
                    max-width: 100%;
                    max-height: 100%;
                    width: 100%;
                    height: 100%;
                  " :src="panelGroupPreview" :preview-src-list="[panelGroupPreview]" show-progress fit="contain" />
              </div>
              <div v-else class="preview-placeholder">
                <el-icon :size="35">
                  <Picture />
                </el-icon>
                <el-text v-if="
                  currentPanelNode?.panelInfo?.design_status === '生成中'
                ">生成中，请稍候</el-text>
                <el-text v-else>暂无面板组预览图</el-text>
              </div>
            </div>
          </div>

          <div class="table-section">
            <div class="section-header">
              <span>面板组合配置</span>
              <div>
                <el-tooltip :content="!currentPanelNode
                  ? '请先选择面板组'
                  : !isAllPanelsConfigured
                    ? '请先完成所有面板的配置'
                    : '点击生成预览图'
                  " placement="top">
                  <el-button size="small" type="primary" @click="debouncedShowPanelGroupPreview"
                    :disabled="!currentPanelNode || !isAllPanelsConfigured">
                    生成预览图
                  </el-button>
                </el-tooltip>
              </div>
            </div>

            <!-- 新增：表格和预览图的上下布局容器 -->
            <div class="table-preview-container">
              <!-- 上半部分：表格（高度减半） -->
              <div class="table-content" style="height: 19.3vh">
                <el-table :data="panelConfigTable" border style="width: 100%; height: 100%" size="small">
                  <!-- 表格列保持不变 -->
                  <el-table-column label="面板序号" max-width="80" align="center">
                    <template #default="{ $index }">
                      {{ $index + 1 }}
                    </template>
                  </el-table-column>

                  <el-table-column label="状态" max-width="75" align="center">
                    <template #default="{ row, $index }">
                      <div v-if="row.panelUnitGuid">
                        <el-tag type="success">已配置</el-tag>
                      </div>
                      <div v-else>
                        <el-tag type="info">未配置</el-tag>
                      </div>
                    </template>
                  </el-table-column>

                  <el-table-column label="面板" min-width="200" align="center">
                    <template #default="{ row, $index }">
                      <el-select v-model="row.panelUnitGuid" placeholder="请选择面板单元" style="width: 100%" size="small"
                        @change="handlePanelUnitChange($index, row.panelUnitGuid)" filterable>
                        <el-option v-for="unit in availablePanelUnits" :key="unit.guid" :label="unit.panel_name"
                            :value="unit.guid" style="height: 60px; padding: 10px;">
                          <div style="display: flex; align-items: center;">
                            <el-image v-if="unit.thumbnail_large" :src="config.PicAds + unit.thumbnail_large"
                              style="width: 50px; height: 50px; margin-right: 10px;" fit="contain"
                              :preview-src-list="[config.PicAds + unit.thumbnail_large]" preview-teleported>
                              <template #error>
                                <div class="image-slot"
                                  style="width: 100px; height: 100px; display: flex; justify-content: center; align-items: center; background-color: #f5f7fa;">
                                  <el-icon>
                                    <Picture />
                                  </el-icon>
                                </div>
                              </template>
                            </el-image>
                            <div v-else
                              style="width: 100px; height: 100px; margin-right: 10px; display: flex; justify-content: center; align-items: center; background-color: #f5f7fa;">
                              <el-icon>
                                <Picture />
                              </el-icon>
                            </div>
                            <span>{{ unit.panel_name }}</span>
                          </div>
                        </el-option>
                      </el-select>
                    </template>
                  </el-table-column>

                  <el-table-column label="操作" width="90" align="center">
                    <template #default="{ row, $index }">
                      <el-button size="small" link :type="currentPanelUnit === row.panelUnitGuid
                        ? 'info'
                        : 'primary'
                        " @click="editPanelUnitConfig(row)" :disabled="!row.panelUnitGuid">
                        {{
                          currentPanelUnit === row.panelUnitGuid
                            ? "编辑中"
                            : "编辑"
                        }}
                      </el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </div>

              <!-- 下半部分：新增的面板组预览图 -->
              <div class="preview-below-table">
                <div class="preview-content">
                  <div v-if="panelGroupPreviewThumbnail" class="preview-image">
                    <el-image style="
                        max-width: 100%;
                        max-height: 100%;
                        width: 100%;
                        height: 100%;
                      " :src="panelGroupPreviewThumbnail" fit="contain" />
                  </div>
                  <div v-else class="preview-placeholder">
                    <el-icon :size="35">
                      <Picture />
                    </el-icon>
                    <el-text>暂无面板组预览图</el-text>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 单个面板配置 -->
      <div class="right-bottom">
        <div class="panel-unit-config-container">
          <!-- 左边预览图区域保持不变 -->
          <div class="preview-section-down">
            <div class="section-header">
              <span>单面板预览图</span>
              <div>
                <el-tooltip content="刷新预览图" placement="top">
                  <el-button size="small" type="info" @click="refreshPanelUnitPreview" :disabled="!currentPanelUnit">
                    刷新预览
                  </el-button>
                </el-tooltip>
              </div>
            </div>
            <div class="preview-content">
              <div v-if="singlePanelPreview" class="preview-image">
                <el-image style="
                    max-width: 97%;
                    max-height: 100%;
                    width: 97%;
                    height: 100%;
                  " :src="singlePanelPreview" :preview-src-list="[singlePanelPreview]" show-progress fit="contain" />
              </div>
              <div v-else class="preview-placeholder">
                <el-icon :size="35">
                  <Picture />
                </el-icon>
                <el-text v-if="
                  currentPanelUnitObj &&
                  currentPanelUnitObj.design_status === '生成中'
                ">生成中，请稍候</el-text>
                <el-text v-else>暂无面板预览图</el-text>
              </div>
            </div>
          </div>

          <!-- 右边表单区域调整为左右结构 -->
          <div class="form-section">
            <div class="section-header">
              <span>单个面板配置{{
                currentPanelUnitObj &&
                  currentPanelUnitObj.design_status === "生成中"
                  ? "（生成中）"
                  : ""
              }}</span>
              <div>
                <el-tooltip content="点击生成单个面板预览图" placement="top">
                  <el-button size="small" type="primary" @click="debouncedShowSinglePanelPreview"
                    :disabled="!currentPanelUnit">
                    生成预览图
                  </el-button>
                </el-tooltip>
              </div>
            </div>

            <!-- 新增：左右布局容器 -->
            <div class="form-content-container">
              <!-- 左侧：新增的pattern预览图 -->
              <div class="pattern-preview-section">
                <div class="preview-content">
                  <div v-if="singlePanelPatternPreview" class="preview-image">
                    <el-image style="
                        max-width: 100%;
                        max-height: 100%;
                        width: 100%;
                        height: 100%;
                      " :src="singlePanelPatternPreview" fit="contain" />
                  </div>
                  <div v-else class="preview-placeholder">
                    <el-icon :size="35">
                      <Picture />
                    </el-icon>
                    <el-text>暂无面板模型预览图</el-text>
                  </div>
                </div>
              </div>

              <!-- 右侧：表格（宽度缩小） -->
              <div class="table-content" style="width: 70%; height: 39.8vh">
                <el-table ref="mergedPanelUnitTable" :data="mergedPanelUnitForm" border
                  style="width: 100%; height: 100%" size="small" highlight-current-row
                  @current-change="handleMergedPanelUnitRowChange" @row-click="handleMergedPanelUnitRowClick"
                  @change="handleUserEdit">
                  <!-- 表格列保持不变 -->
                  <el-table-column label="位置" min-width="60" align="center">
                    <template #default="{ row }">
                      <span>{{ row.locationName }}</span>
                      <span v-if="row.locationName.length <= 2">号键</span>
                    </template>
                  </el-table-column>

                  <el-table-column label="图标" min-width="100" align="center">
                    <template #default="{ row }">
                      <div v-if="row.icon && row.icon.content" class="icon-preview-cell">
                        <el-image style="
                            max-width: 22px;
                            max-height: 22px;
                            width: 22px;
                            height: 22px;
                          " :src="getIconPreviewUrl(row.icon)" @click="openIconDialog(row)" fit="contain"
                          preview-teleported>
                          <template #error>
                            <div class="image-slot">
                              <el-icon>
                                <Picture />
                              </el-icon>
                            </div>
                          </template>
                        </el-image>
                        <el-button size="small" link type="primary" @click="openIconDialog(row)"
                          style="margin-left: 5px">
                          更换
                        </el-button>
                      </div>
                      <el-button v-else size="small" link @click="openIconDialog(row)" type="primary">
                        选择图标
                      </el-button>
                    </template>
                  </el-table-column>

                  <el-table-column label="中文" min-width="90" align="center">
                    <template #default="{ row }">
                      <el-button size="small" link @click="openChineseDialog(row)" :type="row.chinese && row.chinese.content ? '' : 'primary'
                        ">
                        {{
                          row.chinese && row.chinese.content
                            ? row.chinese.content
                            : "编辑中文"
                        }}
                      </el-button>
                    </template>
                  </el-table-column>

                  <el-table-column label="英文" min-width="90" align="center">
                    <template #default="{ row }">
                      <el-button size="small" link @click="openEnglishDialog(row)" :type="row.english && row.english.content ? '' : 'primary'
                        ">
                        {{
                          row.english && row.english.content
                            ? row.english.content
                            : "编辑英文"
                        }}
                      </el-button>
                    </template>
                  </el-table-column>

                  <el-table-column label="背光" min-width="50" align="center">
                    <template #default="{ row, $index }">
                      <div class="backlight-control">
                        <el-checkbox v-model="row.backlightEnabled" @change="handleBacklightToggle(row, $index)"
                          style="margin-right: 8px">
                        </el-checkbox>
                      </div>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 新增面板组对话框 -->
    <el-dialog v-model="showAddPanelDialog" width="1200px" :close-on-click-modal="false"
      :title="editingPanelGuid ? '编辑面板组' : '新增面板组'" :close-on-press-escape="false">
      <div class="dialog-content">
        <!-- 左侧区域：系列选择表格 -->
        <div class="dialog-left">
          <div class="section-title">请选择系列</div>
          <el-table :data="filteredSeriesList" border highlight-current-row @row-click="handleSeriesChange"
            style="width: 100%" height="500">
            <el-table-column label="系列名称 版本" min-width="150">
              <template #default="{ row }">
                {{ row.Series }}_{{ row.Version }}
              </template>
            </el-table-column>
          </el-table>
        </div>

        <!-- 中间区域：模型选择表格 -->
        <div class="dialog-middle">
          <div class="section-title">
            {{ selectedSeries ? "请选择模型" : "请先选择系列" }}
          </div>
          <div class="model-selectors">
            <!-- PanelCount选择器 -->
            <div class="selector-row">
              <span class="selector-label">面板数:</span>
              <el-select v-model="selectedPanelCount" placeholder="请选择面板数" @change="updateModelList"
                :disabled="!selectedSeries">
                <el-option v-for="count in panelCountOptions" :key="count" :label="count" :value="count" />
              </el-select>
            </div>

            <!-- Direction选择器 -->
            <div class="selector-row">
              <span class="selector-label">方向:</span>
              <el-select v-model="selectedDirection" placeholder="请选择方向" @change="updateModelList"
                :disabled="!selectedSeries">
                <el-option v-for="dir in directionOptions" :key="dir" :label="dir" :value="dir" />
              </el-select>
            </div>

            <!-- Color选择器 -->
            <div class="selector-row">
              <span class="selector-label">颜色:</span>
              <el-select v-model="selectedColor" placeholder="请选择颜色" @change="updateModelList"
                :disabled="!selectedSeries">
                <el-option v-for="color in colorOptions" :key="color" :label="color" :value="color" />
              </el-select>
            </div>
            <!-- 位置选择器 -->
            <div class="selector-row">
              <span class="selector-label">Logo位置:</span>
              <el-select v-model="selectedLogoPosition" placeholder="请选择Logo位置" clearable
                @change="handleLogoPositionChange" :disabled="!selectedModel">
                <el-option v-for="position in logoPositionOptions" :key="position.value" :label="position.label"
                  :value="position.value" />
              </el-select>
            </div>

            <!-- Logo图片选择器 -->
            <div class="selector-row" v-if="selectedLogoPosition !== 'none'">
              <span class="selector-label">Logo图片:</span>
              <el-select v-model="selectedLogo" placeholder="请选择Logo图片" @change="handleLogoChange" clearable
                :disabled="!selectedModel || selectedLogoPosition === 'none'">
                <el-option v-for="logo in logoList" :key="logo.ID" :label="formatNameFront12(logo.KeyName)"
                  :value="logo">
                  <div style="
                      display: flex;
                      align-items: center;
                      justify-content: space-between;
                      width: 100%;
                    ">
                    <el-image v-if="logo.PreviewPath" :src="config.PicAds + logo.PreviewPath" style="
                        max-width: 60px;
                        max-height: 23px;
                        width: 60px;
                        height: 23px;
                        margin-right: 8px;
                      " fit="contain" />
                    <span style="flex: 1; text-align: left">{{
                      formatNameFront12(logo.KeyName)
                      }}</span>
                  </div>
                </el-option>
              </el-select>
            </div>
          </div>
        </div>

        <!-- 右侧区域：预览图 -->
        <div class="dialog-right">
          <div class="section-title">预览</div>
          <div class="preview-container">
            <div v-if="selectedSeriesPreview" class="preview-image">
              <div class="preview-info">
                <el-image style="
                    width: 100%;
                    height: 100%;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                  " :src="selectedSeriesPreview" fit="contain" />
              </div>
            </div>
            <div v-else class="preview-placeholder">
              <el-icon :size="40">
                <Picture />
              </el-icon>
              <el-text>选择系列以查看预览</el-text>
            </div>
          </div>
        </div>
      </div>

      <!-- 表单信息移到对话框底部 -->
      <div class="dialog-bottom">
        <el-form :model="newPanelForm" label-width="100px" inline>
          <el-form-item label="面板组名称" required>
            <el-input v-model="newPanelForm.panel_list_name" placeholder="请输入面板组名称" style="width: 200px" />
          </el-form-item>
          <el-form-item label="雕刻数量" required>
            <el-input-number v-model="newPanelForm.carving_quantity" placeholder="请输入雕刻数量" :min="1"
              style="width: 200px" />
          </el-form-item>
          <el-form-item label="面板位置" required>
            <el-input v-model="newPanelForm.position" placeholder="请输入面板位置" style="width: 200px" />
          </el-form-item>
          <!--          <el-form-item label="备注">
                      <el-input v-model="newPanelForm.remarks" placeholder="请输入备注信息" style="width: 400px;" />
                    </el-form-item>-->
        </el-form>
      </div>

      <template #footer>
        <el-button @click="showAddPanelDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmAddPanel">确定</el-button>
      </template>
    </el-dialog>

    <!-- 新增面板单元对话框 -->
    <el-dialog v-model="showAddPanelUnitDialog" width="1200px" :close-on-click-modal="false"
      :title="isEditPanelUnit ? '编辑面板单元' : '新增面板单元'" :close-on-press-escape="false">
      <div class="dialog-content">
        <!-- 左侧区域：系列选择表格 -->
        <div class="dialog-left">
          <div class="section-title">请选择系列</div>
          <el-table :data="filteredSeriesList" border highlight-current-row @row-click="handleSeriesChangeForUnit"
            style="width: 100%" height="500">
            <el-table-column label="系列名称 版本" min-width="150">
              <template #default="{ row }">
                {{ row.Series }}_{{ row.Version }}
              </template>
            </el-table-column>
          </el-table>
        </div>

        <!-- 中间区域：模型选择区域 -->
        <div class="dialog-middle">
          <div class="section-title">
            {{ selectedSeriesForUnit ? "请选择模型" : "请先选择系列" }}
          </div>
          <div class="model-selectors">
            <!-- Direction选择器 -->
            <div class="selector-row">
              <span class="selector-label">方向:</span>
              <el-select v-model="selectedDirectionForUnit" placeholder="请选择方向" @change="updateModelListForUnit"
                :disabled="!selectedSeriesForUnit || directionOptionsForUnit.length === 0
                  ">
                <el-option v-for="dir in directionOptionsForUnit" :key="dir" :label="dir" :value="dir" />
              </el-select>
            </div>

            <!-- Color选择器 -->
            <div class="selector-row">
              <span class="selector-label">颜色:</span>
              <el-select v-model="selectedColorForUnit" placeholder="请选择颜色" @change="updateModelListForUnit" :disabled="!selectedSeriesForUnit || colorOptionsForUnit.length === 0
                ">
                <el-option v-for="color in colorOptionsForUnit" :key="color" :label="color" :value="color" />
              </el-select>
            </div>

            <!-- 面板选择器 -->
            <div class="selector-row">
              <span class="selector-label">面板:</span>
              <el-select v-model="selectedPatternForUnit" placeholder="请选择面板" style="width: 100%" :disabled="!selectedSeriesForUnit || patternsListForUnit.length === 0
                ">
                <el-option v-for="pattern in patternsListForUnit" :key="pattern.ID"
                  :label="formatNameFront12(pattern.PatternName)" :value="pattern.ID" />
              </el-select>
            </div>
          </div>
        </div>

        <!-- 右侧区域：预览图 -->
        <div class="dialog-right">
          <div class="section-title">预览</div>
          <div class="preview-container">
            <div v-if="selectedSeriesPreviewForUnit" class="preview-image">
              <div class="preview-info">
                <el-image style="
                    max-width: 100%;
                    max-height: 100%;
                    width: 100%;
                    height: 100%;
                  " :src="selectedSeriesPreviewForUnit" :preview-src-list="[selectedSeriesPreviewForUnit]"
                  show-progress fit="contain" />
              </div>
            </div>
            <div v-else class="preview-placeholder">
              <el-icon :size="40">
                <Picture />
              </el-icon>
              <el-text>选择系列以查看预览</el-text>
            </div>
          </div>
        </div>
      </div>

      <!-- 表单信息 -->
      <div class="dialog-bottom">
        <el-form :model="newPanelUnitForm" label-width="130px" inline>
          <el-form-item label="面板单元名称" required>
            <el-input v-model="newPanelUnitForm.panel_name" placeholder="请输入面板单元名称" style="width: 300px" />
          </el-form-item>
          <!--          <el-form-item label="备注">
                      <el-input v-model="newPanelUnitForm.remarks" placeholder="请输入备注信息" style="width: 450px;" />
                    </el-form-item>-->
        </el-form>
      </div>

      <template #footer>
        <el-button @click="showAddPanelUnitDialog = false">取消</el-button>
        <el-button type="primary" @click="isEditPanelUnit ? updatePanelUnit() : confirmAddPanelUnit()"
          :disabled="!selectedSeriesForUnit || !selectedPatternForUnit">
          {{ isEditPanelUnit ? "更新" : "确定" }}
        </el-button>
      </template>
    </el-dialog>

    <!-- 图标选择对话框 -->
    <el-dialog v-model="iconDialogVisible" title="选择图标" fullscreen>
      <div class="icon-select-dialog">
        <!-- 图标库选择器 -->
        <div class="icon-library-selector">
          <span class="selector-label">搜索图标:</span>
          <el-input v-model="iconSearchQuery" placeholder="输入图标名称搜索" style="width: 200px" size="small" clearable
            @input="handleIconSearch">
            <template #prefix>
              <el-icon>
                <Search />
              </el-icon>
            </template>
          </el-input>
        </div>

        <!-- 图标网格 -->
        <div class="icon-grid-container">
          <!-- 左侧：图标库选择表格 -->
          <div class="icon-library-table-container">
            <el-table :data="iconLibraryList" border highlight-current-row @row-click="handleIconLibraryRowClick"
              style="width: 100%" height="100%" size="small">
              <el-table-column label="图标库" min-width="150">
                <template #default="{ row }">
                  {{ row.Series }}_{{ row.Version }}
                </template>
              </el-table-column>
            </el-table>
          </div>

          <!-- 右侧：图标网格 -->
          <div class="icon-grid-wrapper">
            <div class="icon-grid">
              <div v-for="icon in currentIconList" :key="icon.ID" class="icon-item" @click="saveIconConfig(icon)">
                <div class="icon-preview">
                  <el-image v-if="icon.PreviewPath" :src="config.PicAds + icon.PreviewPath" fit="contain" style="
                      max-width: 40px;
                      max-height: 40px;
                      width: 40px;
                      height: 40px;
                    " />
                  <el-icon v-else :size="60">
                    <Picture />
                  </el-icon>
                </div>
                <div class="icon-name">
                  {{ formatNameFront12(icon.KeyName) }}
                </div>

                <!--<div class="icon-library">{{ getLibraryName(icon.FID) }}</div>-->
              </div>
            </div>

            <!-- 空状态 -->
            <div v-if="currentIconList.length === 0" class="empty-icons">
              <el-icon :size="48">
                <Picture />
              </el-icon>
              <p>该图标库暂无图标</p>
            </div>
          </div>
        </div>
      </div>

      <!--       <template #footer>
              <el-button @click="iconDialogVisible = false">取消</el-button>
           <el-button type="primary" @click="iconDialogVisible = false">确定</el-button>
      </template>-->
    </el-dialog>

    <!-- 中文编辑对话框 -->
    <el-dialog v-model="chineseDialogVisible" title="编辑中文内容" width="500px" :close-on-press-escape="false">
      <el-form :model="currentEditingLocation?.chinese" label-width="80px">
        <el-form-item label="内容">
          <el-input v-model="currentEditingLocation.chinese.content" placeholder="请输入中文内容" maxlength="5" minlength="1"
            show-word-limit />
        </el-form-item>
        <el-form-item label="字体">
          <el-select v-model="currentEditingLocation.chinese.font" placeholder="请选择字体">
            <el-option v-for="font in fontList" :key="font.ID" :label="font.FontName" :value="font.FontName" />
          </el-select>
        </el-form-item>
        <el-form-item label="字号">
          <el-input-number v-model="currentEditingLocation.chinese.size" :min="6" :max="14" :step="0.2" :precision="1"
            controls-position="right" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="chineseDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveChineseConfig">确定</el-button>
      </template>
    </el-dialog>

    <!-- 英文编辑对话框 -->
    <el-dialog v-model="englishDialogVisible" title="编辑英文内容" width="500px" :close-on-press-escape="false">
      <el-form :model="currentEditingLocation?.english" label-width="80px">
        <el-form-item label="内容">
          <el-input v-model="currentEditingLocation.english.content" placeholder="请输入英文内容" maxlength="14" minlength="4"
            show-word-limit />
        </el-form-item>
        <el-form-item label="字体">
          <el-select v-model="currentEditingLocation.english.font" placeholder="请选择字体">
            <el-option v-for="font in fontList" :key="font.ID" :label="font.FontName" :value="font.FontName" />
          </el-select>
        </el-form-item>
        <el-form-item label="字号">
          <el-input-number v-model="currentEditingLocation.english.size" :min="4" :max="10" :step="0.2" :precision="1"
            controls-position="right" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="englishDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveEnglishConfig">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {
  ref,
  onMounted,
  nextTick,
  inject,
  computed,
  watch,
  onUnmounted,
} from "vue";
import { createAxiosInstance } from "../../axios.js";
import JSZip from "jszip";
import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
import { Picture } from "@element-plus/icons-vue";

// ==================== 引入外部变量 ====================
const formatDate = inject("formatDate");
const config = inject("config"); // config.PicAds 是图片根路径

// ==================== HTTP 实例 ====================
const cloudHttp = createAxiosInstance(0);
const localHttp = createAxiosInstance(1);
/* 测试方法 */
const test123 = async () => {
  const rs = await localHttp.post(
    "PanelSelection/",
    JSON.stringify({ GUID: "BB_20251204_003" })
  );
  console.log(rs);
}
// ==================== 响应式变量 ====================

// 项目相关变量
const projectList = ref([]);
const selectedProjectId = ref(null);
const isProjectLocked = ref(false);
const treeData = ref([]);
// el-tree 组件引用（用于程序化选中节点）
const projectTree = ref(null);

// 树结构相关变量
const treeProps = { label: "name", children: "children" };
const unitTableData = ref([]);
const isUserEditingPanelUnit = ref(false);

// 面板组对话框相关变量
const showAddPanelDialog = ref(false);
const currentRoomData = ref(null);
const editingPanelGuid = ref(null);
const seriesList = ref([]);
const selectedSeries = ref(null);
const selectedModel = ref(null);
const allModels = ref([]);
const filteredModels = ref([]);
const selectedPanelCount = ref("");
const selectedDirection = ref("");
const selectedColor = ref("");
const panelCountOptions = ref([]);
const directionOptions = ref([]);
const colorOptions = ref([]);

// LOGO配置
const logoPositionOptions = ref([
  { label: "左下", value: "left" },
  { label: "右下", value: "right" },
  { label: "无LOGO", value: "none" },
]);
const selectedLogoPosition = ref("");
const selectedLogo = ref(null);
const logoList = ref([]);
const logoConfig = ref({
  LogoPosition: "",
  LogoFileName: "",
  LogoIndexNumber: "",
});
// 新增面板单元对话框相关变量
const showAddPanelUnitDialog = ref(false);
const selectedSeriesForUnit = ref(null);
const selectedDirectionForUnit = ref("");
const selectedColorForUnit = ref("");
const selectedPatternForUnit = ref("");
const patternsListForUnit = ref([]);
const filteredModelsForUnit = ref([]);
const directionOptionsForUnit = ref([]);
const colorOptionsForUnit = ref([]);
const selectedSeriesPreviewForUnit = ref([]);
const isEditPanelUnit = ref(false);
const currentEditPanelUnit = ref(null);
// 面板修改列表变量
const mergedPanelUnitForm = ref([]);
const currentMergedPanelUnitRow = ref(null); // 当前选中的mergedPanelUnitForm表格行
// 复制面板相关变量
const showCopyPanelDialog = ref(false);
const copyPanelUnitRow = ref(null);
const selectedCopyProjectId = ref(null);
const selectedCopyProjectGuid = ref(null);
const mergedPanelUnitTable = ref(null); // 表格引用
const iconDialogVisible = ref(false);
const chineseDialogVisible = ref(false);
const englishDialogVisible = ref(false);
const currentEditingLocation = ref(null);
const currentEditingType = ref("");
// 面板单元表单
const newPanelUnitForm = ref({
  panel_name: "",
  remarks: "",
});

// 面板配置相关变量
const currentPanelNode = ref(null);
const patternsList = ref([]);
const panelConfigTable = ref([]);

// 面板单元配置相关变量
const currentPanelUnit = ref(null);
const panelUnitForm = ref([]);
const fontList = ref([]);

// ==================== 项目总览图参数（GetAllProjectCDR） ====================
const showProjectCdrDialog = ref(false);
const projectCdrGuid = ref("");
const projectCdrProjectName = ref("");
const projectCdrEnums = ref({
  protocols: ["强电无线", "弱电485"],
  switchSeries: ["T1水立方", "T1水晶方", "T3水星阁"],
  socketSeries: ["玻璃", "塑料", "无"],
});

const projectCdrForm = ref({
  Protocol: "强电无线",
  SwitchSeries: "T1水立方",
  SocketSeries: "玻璃",
  ChineseFont: "思源黑体",
  ChineseFontSize: 11.0,
  EnglishFont: "Futura Std Medium",
  EnglishFontSize: 7.0,
});

const getProjectCdrStorageKey = (guid) => `GetAllProjectCDR_Params_${guid}`;

const loadProjectCdrParams = (guid) => {
  try {
    const raw = localStorage.getItem(getProjectCdrStorageKey(guid));
    if (!raw) return;
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object") return;
    projectCdrForm.value = {
      ...projectCdrForm.value,
      ...parsed,
    };
  } catch {
    // ignore
  }
};

const saveProjectCdrParams = (guid) => {
  try {
    localStorage.setItem(getProjectCdrStorageKey(guid), JSON.stringify(projectCdrForm.value));
  } catch {
    // ignore
  }
};

const applyProjectCdrParamsFromWebProject = (webProjectRow) => {
  if (!webProjectRow || typeof webProjectRow !== "object") return;

  const normalizeNumberOrNull = (v) => {
    if (v === null || v === undefined || v === "") return null;
    const n = Number(v);
    return Number.isFinite(n) ? n : null;
  };

  projectCdrForm.value = {
    ...projectCdrForm.value,
    Protocol: webProjectRow.protocol ?? projectCdrForm.value.Protocol,
    SwitchSeries: webProjectRow.switch_series ?? projectCdrForm.value.SwitchSeries,
    SocketSeries:
      webProjectRow.socket_series === ""
        ? "无"
        : (webProjectRow.socket_series ?? projectCdrForm.value.SocketSeries),
    ChineseFont: webProjectRow.cn_font ?? projectCdrForm.value.ChineseFont,
    ChineseFontSize: normalizeNumberOrNull(webProjectRow.cn_font_size) ?? projectCdrForm.value.ChineseFontSize,
    EnglishFont: webProjectRow.en_font ?? projectCdrForm.value.EnglishFont,
    EnglishFontSize: normalizeNumberOrNull(webProjectRow.en_font_size) ?? projectCdrForm.value.EnglishFontSize,
  };
};

const ensureProjectCdrDefaults = () => {
  if (!projectCdrForm.value.Protocol) projectCdrForm.value.Protocol = "强电无线";
  if (!projectCdrForm.value.SwitchSeries) projectCdrForm.value.SwitchSeries = "T1水立方";
  // 后端约定：SocketSeries 为空字符串代表“无”，UI 用“无”表示
  if (projectCdrForm.value.SocketSeries === "") projectCdrForm.value.SocketSeries = "无";
  if (!projectCdrForm.value.SocketSeries) projectCdrForm.value.SocketSeries = "玻璃";
  if (!projectCdrForm.value.ChineseFont) projectCdrForm.value.ChineseFont = "思源黑体";
  if (projectCdrForm.value.ChineseFontSize === null || projectCdrForm.value.ChineseFontSize === undefined)
    projectCdrForm.value.ChineseFontSize = 11.0;
  if (!projectCdrForm.value.EnglishFont) projectCdrForm.value.EnglishFont = "Futura Std Medium";
  if (projectCdrForm.value.EnglishFontSize === null || projectCdrForm.value.EnglishFontSize === undefined)
    projectCdrForm.value.EnglishFontSize = 7.0;
};

const loadProjectCdrEnums = async () => {
  try {
    const rs = await fetchData("PanelSelection/GetProjectCdrEnums", {});
    if (!rs || typeof rs !== "object") return;

    if (Array.isArray(rs.protocols)) projectCdrEnums.value.protocols = rs.protocols;
    if (Array.isArray(rs.switchSeries)) projectCdrEnums.value.switchSeries = rs.switchSeries;
    if (Array.isArray(rs.socketSeries)) projectCdrEnums.value.socketSeries = rs.socketSeries;
  } catch {
    // ignore
  }
};

// 防抖相关变量
const lastPanelGroupPreviewClickTime = ref(0);
const lastSinglePanelPreviewClickTime = ref(0);
const DEBOUNCE_DELAY = 1000; // 1000ms防抖延迟

// 防抖函数
const debounceClick = (lastClickTime, callback) => {
  const now = Date.now();
  if (now - lastClickTime.value < DEBOUNCE_DELAY) {
    return false; // 在防抖时间内，不执行回调
  }
  lastClickTime.value = now;
  callback();
  return true;
};

// 面板组预览图生成防抖函数
const debouncedShowPanelGroupPreview = () => {
  return debounceClick(lastPanelGroupPreviewClickTime, () => {
    showPreview(0);
  });
};

// 单个面板预览图生成防抖函数
const debouncedShowSinglePanelPreview = () => {
  return debounceClick(lastSinglePanelPreviewClickTime, () => {
    showSinglePanelPreview();
  });
};

// 生成历史记录
const generationHistory = ref([]);
// 生成状态枚举
const GenerationStatus = {
  IN_PROGRESS: "生成中",
  COMPLETED: "已完成",
  ERROR: "生成错误",
  CANCELLED: "已取消",
};
// 项目状态跟踪
const isProjectGenerating = ref(false);
// 项目下载可用性跟踪
const isProjectDownloadAvailable = ref(false);
// 生成类型枚举
const GenerationType = {
  PREVIEW: "组合预览",
  CDR: "CDR文件",
  SINGLE_PANEL: "单面板",
  PROJECT: "项目",
};
const allModelsForUnit = ref([]);
const selectedModelForUnit = ref(null);

// 进度更新相关变量
const progressIntervals = ref(new Map()); // 存储每个生成任务的进度更新间隔ID

// 图片预览相关变量
const selectedSeriesPreview = ref("");
const singlePanelPreview = ref("");

// 图标相关变量
const iconLibraryList = ref([]); // 图标库文件列表
const selectedIconLibrary = ref(""); // 当前选中的图标库文件ID
const iconOptions = ref({}); // 图标数据，以文件ID为键，存储图标数组
const iconSearchQuery = ref(""); // 图标搜索查询字符串

// 表单数据
const newPanelForm = ref({
  panel_list_name: "",
  gang_series: "",
  model_type: "",
  panel_count: null,
  gang_material_id: 0,
  remarks: "",
  logo_json: "{}",
  carving_quantity: null, // 新增雕刻数量字段
  position: "", // 新增位置字段
});
// 加载遮罩实例
let loadingInstance = null;
// 轮询相关变量
const pollingInterval = ref(null);
const isPollingActive = ref(false);
const pollingItems = ref({
  panelLists: new Set(), // 存储需要轮询的面板组GUID
  panelUnits: new Set(), // 存储需要轮询的面板单元GUID
  projects: new Set(), // 存储需要轮询的项目GUID
});
// ==================== 计算属性 ====================
// 检查是否有生成中的元素
const hasGeneratingItems = computed(() => {
  // 检查generationHistory中是否有正在生成的记录
  const hasGeneratingHistory = generationHistory.value.some(
    (record) => record.status === GenerationStatus.IN_PROGRESS
  );
  // 保留原有检查逻辑以确保兼容性
  const hasPanelGroupGenerating =
    currentPanelNode.value?.panelInfo?.design_status === "生成中";
  const hasPanelUnitGenerating =
    currentPanelUnitObj.value &&
    currentPanelUnitObj.value.design_status === "生成中";
  return (
    hasGeneratingHistory || hasPanelGroupGenerating || hasPanelUnitGenerating
  );
});
/**
 * 获取当前选中的面板单元对象
 */
const currentPanelUnitObj = computed(() => {
  try {
    if (
      !currentPanelUnit.value ||
      !unitTableData.value ||
      !Array.isArray(unitTableData.value)
    ) {
      return null;
    }
    const unit = unitTableData.value.find(
      (unit) => unit.guid === currentPanelUnit.value
    );
    return unit || null;
  } catch (error) {
    console.error("获取当前面板单元对象失败:", error);
    return null;
  }
});
const currentIconList = computed(() => {
  // 获取当前选中的图标库列表
  let icons = selectedIconLibrary.value
    ? iconOptions.value[selectedIconLibrary.value] || []
    : [];

  // 如果有搜索查询，进行过滤
  if (iconSearchQuery.value && iconSearchQuery.value.trim()) {
    const query = iconSearchQuery.value.trim().toLowerCase();
    icons = icons.filter((icon) => {
      // 使用formatNameFront12处理图标名称，然后进行模糊匹配
      const formattedName = formatNameFront12(icon.KeyName).toLowerCase();
      return formattedName.includes(query);
    });
  }

  return icons;
});

const availablePanelUnits = computed(() => {
  if (!unitTableData.value || unitTableData.value.length === 0) {
    return [];
  }
  return unitTableData.value.filter((unit) => unit.is_valid);
});

// 面板单元搜索过滤
const filteredPanelUnits = ref([]);
const filterPanelUnits = (query) => {
  if (!query || query.trim() === '') {
    filteredPanelUnits.value = availablePanelUnits.value;
    return;
  }

  const searchTerm = query.trim().toLowerCase();
  filteredPanelUnits.value = availablePanelUnits.value.filter(unit =>
    unit.panel_name && unit.panel_name.toLowerCase().includes(searchTerm)
  );
};

// 初始化过滤面板单元
watch(availablePanelUnits, (newValue) => {
  filteredPanelUnits.value = newValue;
}, { immediate: true });
/**
 * 面板组预览图
 */
const panelGroupPreview = computed(() => {
  if (!currentPanelNode.value) return "";
  const panelInfo = currentPanelNode.value.panelInfo;

  // 显示面板组的大缩略图
  if (panelInfo.thumbnail_large) {
    return config.PicAds + panelInfo.thumbnail_large;
  }

  return "";
});

const panelGroupPreviewThumbnail = ref("");
watch(
  () => currentPanelNode.value,
  async (newNode) => {
    if (!newNode?.panelInfo?.model_type) {
      panelGroupPreviewThumbnail.value = "";
      return;
    }
    try {
      const model = await fetchData("PanelSelection/IdModelQuery", {
        PID: newNode.panelInfo.gang_material_id,
      });
      if (model && model[0] && model[0].PreviewPath) {
        panelGroupPreviewThumbnail.value = config.PicAds + model[0].PreviewPath;
      } else {
        panelGroupPreviewThumbnail.value = "";
      }
    } catch (error) {
      panelGroupPreviewThumbnail.value = "";
    }
  },
  { immediate: true }
);
/**
 * 检查所有面板是否已配置
 */
const isAllPanelsConfigured = computed(() => {
  if (!panelConfigTable.value.length) return false;
  return panelConfigTable.value.every((item) => {
    return item.panelUnitGuid && item.panelUnitGuid.length === 32;
  });
});

/**
 * 面板选择器去除路径为空的对象
 */
const filteredSeriesList = computed(() => {
  return seriesList.value.filter(
    (row) =>
      row.PreviewPath != undefined &&
      row.PreviewPath != null &&
      row.PreviewPath !== ""
  );
});
/**
 * 将面板单元数据按位置名称合并
 */
const buildMergedPanelUnitForm = () => {
  try {
    const groupedData = {};

    if (
      !panelUnitForm.value ||
      !Array.isArray(panelUnitForm.value) ||
      panelUnitForm.value.length === 0
    ) {
      mergedPanelUnitForm.value = [];
      return;
    }
    panelUnitForm.value.forEach((item) => {
      if (!item || !item.locationName) return;

      const locationParts = item.locationName.split("_");
      let groupKey = "";

      if (locationParts.length >= 3) {
        groupKey = locationParts[2];
      } else {
        groupKey = item.locationName;
      }

      if (!groupKey || groupKey.trim() === "") {
        groupKey = "未分类";
      }

      if (!groupedData[groupKey]) {
        groupedData[groupKey] = {
          locationName: groupKey,
          originalLocationName: item.locationName,
          icon: {},
          chinese: {},
          english: {},
          locations: [],
          backlightColor: "#FFFFFF",
          backlightEnabled: false,
        };
      }

      // 根据类型分配到对应属性
      if (item.type === 1) {
        groupedData[groupKey].icon = {
          ...item,
          locationName: item.locationName,
          backlightColor: item.backlightColor || "#FFFFFF",
          backlightEnabled: item.backlightEnabled || false,
        };
      } else if (item.type === 2) {
        groupedData[groupKey].chinese = {
          ...item,
          locationName: item.locationName,
          backlightColor: item.backlightColor || "#FFFFFF",
          backlightEnabled: item.backlightEnabled || false,
        };
      } else if (item.type === 3) {
        groupedData[groupKey].english = {
          ...item,
          locationName: item.locationName,
          backlightColor: item.backlightColor || "#FFFFFF",
          backlightEnabled: item.backlightEnabled || false,
        };
      }

      // 保存原始位置数据
      groupedData[groupKey].locations.push(item);

      // 设置背光默认值（取第一个非默认值的元素）
      if (item.backlightColor && item.backlightColor !== "#FFFFFF") {
        groupedData[groupKey].backlightColor = item.backlightColor;
        groupedData[groupKey].backlightEnabled = true;
      }
    });
    mergedPanelUnitForm.value =
      Object.values(groupedData).sort(naturalSortSimple);
  } catch (error) {
    console.error("构建合并面板单元表单时出错:", error);
    mergedPanelUnitForm.value = [];
  }
};

const naturalSortSimple = (a, b) => {
  return a.locationName.localeCompare(b.locationName, "zh-CN", {
    numeric: true,
    sensitivity: "base",
  });
};

// ==================== 工具方法 ====================
const formatDate2 = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  return `${year}${month}${day} ${hours}${minutes}${seconds}`;
}
const formatDate1 = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');

  return `${year}${month}${day}`;
}
const handleUserEdit = () => {
  isUserEditingPanelUnit.value = true;

  // 重置标志位，给用户一个编辑窗口期
  if (window.userEditResetTimeout) {
    clearTimeout(window.userEditResetTimeout);
  }

  window.userEditResetTimeout = setTimeout(() => {
    isUserEditingPanelUnit.value = false;
  }, 200); // 恢复原始的200ms设置
};

/**
 * 处理mergedPanelUnitForm表格行变化
 */
const handleMergedPanelUnitRowChange = (newRow) => {
  currentMergedPanelUnitRow.value = newRow;
};

/**
 * 处理mergedPanelUnitForm表格行点击
 */
const handleMergedPanelUnitRowClick = (row) => {
  currentMergedPanelUnitRow.value = row;
};
/**
 * 综合轮询管理
 */
const managePolling = () => {
  // 检查当前是否有生成中的项目
  const shouldPoll = hasGeneratingItems.value;

  if (shouldPoll && !isPollingActive.value) {
    startPolling();
  } /*else if (!shouldPoll && isPollingActive.value) {
      stopPolling();
    }*/
};
/**
 * 启动轮询检查生成状态
 */
const startPolling = () => {
  if (isPollingActive.value) return;

  isPollingActive.value = true;
  console.log("启动轮询检查生成状态...");

  // 生成500ms-2000ms之间的随机时间
  const getRandomInterval = () => {
    return Math.floor(Math.random() * 1500) + 500; // 500-2000ms
  };

  // 使用递归的setTimeout实现随机间隔轮询
  const poll = async () => {
    if (!isPollingActive.value) return;

    try {
      await checkGeneratingStatus();
      if (!singlePanelPreview.value) {
        await refreshPanelUnitPreview();
      }
      if (!panelGroupPreview.value) {
        await refreshPanelGroupPreview();
      }
    } catch (error) {
      console.error("轮询执行出错:", error);
    }

    // 设置下一次轮询的随机间隔
    pollingInterval.value = setTimeout(poll, getRandomInterval());
  };

  // 启动第一次轮询
  poll();
};

/**
 * 停止轮询
 */
const stopPolling = () => {
  if (pollingInterval.value) {
    clearInterval(pollingInterval.value);
    pollingInterval.value = null;
  }
  isPollingActive.value = false;
  pollingItems.value.panelLists.clear();
  pollingItems.value.panelUnits.clear();
  console.log("停止轮询检查");
};

/**
 * 检查项目状态
 */
const checkProjectStatus = async (projectGuid) => {
  try {
    // 调用GetProjectStatus获取项目状态
    const projectStatus = await GetProjectStatus(projectGuid);

    // 查找generationHistory中对应的项目记录
    const projectIndex = generationHistory.value.findIndex(
      record => record.guid === projectGuid && record.type === GenerationType.PROJECT
    );

    if (projectIndex === -1) {
      // 如果记录不存在，从轮询列表中移除
      pollingItems.value.projects.delete(projectGuid);
      return false;
    }

    const record = generationHistory.value[projectIndex];

    // 检查项目是否已完成生成
    if (projectStatus !== GenerationStatus.IN_PROGRESS) {
      // 更新记录状态
      const endTime = new Date();
      generationHistory.value[projectIndex] = {
        ...record,
        status: GenerationStatus.COMPLETED,
        progress: 100,
        progressText: "项目总览图已生成完成",
        completedAt: formatDate(endTime),
        duration: Math.round((endTime.getTime() - record.startTime) / 1000),
      };

      // 从轮询列表中移除
      pollingItems.value.projects.delete(projectGuid);
      isProjectGenerating.value = false;

      return true;
    }

    return false;
  } catch (error) {
    console.error(`检查项目 ${projectGuid} 状态失败:`, error);
    // 从轮询列表中移除错误的项目
    pollingItems.value.projects.delete(projectGuid);
    isProjectGenerating.value = false;
    return false;
  }
};

/**
 * 检查生成状态并更新数据
 */
const checkGeneratingStatus = async () => {
  try {
    let hasUpdates = false;

    // 检查面板组生成状态
    // 遍历所有需要轮询的面板组GUID
    for (const panelListGuid of pollingItems.value.panelLists) {
      try {
        const updated = await checkPanelListStatus(panelListGuid);
        if (updated) hasUpdates = true;
      } catch (error) {
        console.error(`检查面板组 ${panelListGuid} 状态失败:`, error);
      }
    }

    // 检查面板单元生成状态
    if (
      currentPanelUnitObj.value &&
      currentPanelUnitObj.value.design_status === "生成中"
    ) {
      const panelUnitGuid = currentPanelUnit.value;
      const updated = await checkPanelUnitStatus(panelUnitGuid);
      if (updated) hasUpdates = true;
    }

    // 如果有更新，强制重新渲染相关组件
    if (hasUpdates) {
      // 触发响应式更新
      currentPanelNode.value = { ...currentPanelNode.value };
      currentPanelUnit.value = currentPanelUnit.value;
    }

    // 检查项目生成状态
    for (const projectGuid of [...pollingItems.value.projects]) {
      try {
        const updated = await checkProjectStatus(projectGuid);
        if (updated) hasUpdates = true;
      } catch (error) {
        console.error(`检查项目 ${projectGuid} 状态失败:`, error);
      }
    }

    // 如果没有生成中的元素，停止轮询
    if (!hasGeneratingItems.value) {
      stopPolling();
      console.log("所有生成任务已完成，停止轮询");
    }
  } catch (error) {
    console.error("轮询检查生成状态失败:", error);
  }
};

/**
 * 检查面板组状态
 */
const checkPanelListStatus = async (panelListGuid) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/WebPanelListQueryByGuid",
      JSON.stringify({ GUID: panelListGuid })
    );
    if (rs.data.isok && rs.data.response) {
      const data = JSON.parse(rs.data.response);
      if (data.length > 0) {
        const panelInfo = data[0];
        // 检查是否仍然在生成中
        if (panelInfo.design_status !== "生成中") {
          // 更新当前面板组信息
          if (currentPanelNode.value) {
            //currentPanelNode.value.panelInfo = panelInfo;
          }

          // 更新树节点中的面板组信息
          updatePanelNodeInTree(panelListGuid, panelInfo);
          // 更新生成历史记录
          const recordIndex = generationHistory.value.findIndex(
            (record) => record.guid === panelListGuid
          );
          if (recordIndex !== -1) {
            const record = generationHistory.value[recordIndex];
            let updatedRecord;
            if (panelInfo.design_status !== "生成中") {
              const endTime = Date.now();
              const duration = record.startTime
                ? Math.round(((endTime - record.startTime) / 1000) * 10) / 10
                : null;
              updatedRecord = {
                ...record,
                status: GenerationStatus.COMPLETED,
                progress: 100,
                progressText: "图片生成完成",
                completedAt: formatDate(new Date()),
                duration: duration,
              };
            }
            // 使用splice确保响应式更新
            generationHistory.value.splice(recordIndex, 1, updatedRecord);
            // 停止进度间隔
            if (progressIntervals.value.has(record.guid)) {
              clearInterval(progressIntervals.value.get(record.guid));
              progressIntervals.value.delete(record.guid);
            }
            // 将面板组GUID从轮询列表中移除
            pollingItems.value.panelLists.delete(record.guid);
          }

          // 显示不同的成功消息
          const msgRecordIndex = generationHistory.value.findIndex(
            (record) => record.guid === panelListGuid
          );
          if (msgRecordIndex !== -1) {
            ElMessage.success("面板组预览图生成完成！");
          } else {
            ElMessage.success("生成完成！");
          }

          return true; // 返回true表示有更新
        }
      }
    }
    return false;
  } catch (error) {
    console.error("检查面板组状态失败:", error);
    return false;
  }
};

/**
 * 检查面板单元状态
 */
const checkPanelUnitStatus = async (panelUnitGuid) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/WebPanelUnitQueryByGuid",
      JSON.stringify({ GUID: panelUnitGuid })
    );

    if (rs.data.isok && rs.data.response) {
      const data = JSON.parse(rs.data.response);
      if (data.length > 0) {
        const panelUnit = data[0];
        // 检查是否仍然在生成中
        if (panelUnit.design_status !== "生成中") {
          // 更新面板单元列表
          const unitIndex = unitTableData.value.findIndex(
            (u) => u.guid === panelUnitGuid
          );
          if (unitIndex !== -1) {
            unitTableData.value[unitIndex] = panelUnit;
          }

          // 更新当前面板单元对象
          if (currentPanelUnit.value === panelUnitGuid) {
            // 触发响应式更新
            currentPanelUnit.value = panelUnitGuid;
          }

          // 更新生成历史记录
          const recordIndex = generationHistory.value.findIndex(
            (record) => record.guid === panelUnitGuid
          );
          if (recordIndex !== -1) {
            const record = generationHistory.value[recordIndex];
            const endTime = Date.now();
            const duration = record.startTime
              ? Math.round(((endTime - record.startTime) / 1000) * 10) / 10
              : null;
            let updatedRecord;

            if (panelUnit.design_status !== "生成中") {
              // 生成成功
              updatedRecord = {
                ...record,
                status: GenerationStatus.COMPLETED,
                progress: 100,
                progressText: "生成完成",
                completedAt: formatDate(new Date()),
                duration: duration,
              };
            }
            // 使用splice确保响应式更新
            generationHistory.value.splice(recordIndex, 1, updatedRecord);
            // 停止进度间隔
            if (progressIntervals.value.has(record.guid)) {
              clearInterval(progressIntervals.value.get(record.guid));
              progressIntervals.value.delete(record.guid);
            }
          }

          //ElMessage.success("单面板预览图生成完成！");
          return true; // 返回true表示有更新
        }
      }
    }
    return false;
  } catch (error) {
    console.error("检查面板单元状态失败:", error);
    return false;
  }
};

/**
 * 更新树节点中的面板组信息
 */
const updatePanelNodeInTree = (panelGuid, newPanelInfo) => {
  const updateNode = (nodes) => {
    for (let node of nodes) {
      if (node.type === "panel" && node.panelGuid === panelGuid) {
        node.panelInfo = newPanelInfo;
        return true;
      }
      if (node.children && node.children.length > 0) {
        if (updateNode(node.children)) {
          return true;
        }
      }
    }
    return false;
  };

  updateNode(treeData.value);
};
/**
 * 获取当前用户
 */
const getCurrentUser = () => localStorage.getItem("username") || "system";

/**
 * 显示加载遮罩
 */
const showLoading = (text = "加载中...") => {
  loadingInstance = ElLoading.service({
    lock: true,
    text: text,
    background: "rgba(0, 0, 0, 0)",
  });
};

/**
 * 隐藏加载遮罩
 */
const hideLoading = () => {
  if (loadingInstance) {
    loadingInstance.close();
    loadingInstance = null;
  }
};

// ==================== 格式化方法 ====================

const formatNameFront1 = (name) => (name ? name.replace(/^[^_]+_/, "") : "");
const formatNameFront12 = (name) => {
  if (!name) return "";
  const parts = name.split("_");
  if (parts.length < 4) return "";
  return parts.slice(1, -2).join("_");
};
const formatNameFront22 = (name) => {
  if (!name) return "";
  const parts = name.split("_");
  if (parts.length < 4) return "";
  return parts.slice(2, -2).join("_");
};
const formatNameFront3 = (name) => {
  if (!name) return "";
  const match = name.match(/^[^_]*_[^_]*_([^_]*)/);
  return match ? match[1] : null;
};

/**
 * 处理图标搜索
 */
const handleIconSearch = () => {
  // 这个方法会在currentIconList计算属性中使用
  // 实际的过滤逻辑在计算属性中实现
};

// ==================== 数据库操作封装 ====================

/**
 * 获取数据
 */
const fetchData = async (endpoint, query = {}) => {
  try {
    const rs = await localHttp.post(endpoint, JSON.stringify(query));
    return rs.data.isok && rs.data.response ? JSON.parse(rs.data.response) : [];
  } catch (error) {
    console.error(`获取${endpoint}数据失败:`, error);
    return [];
  }
};

/**
 * 更新数据库
 */
const updateDatabase = async (endpoint, data) => {
  try {
    const rs = await localHttp.post(endpoint, JSON.stringify(data));
    if (!rs.data.isok) {
      console.error(`API返回错误:`, rs.data);
      throw new Error(rs.data.message);
    }
    return rs.data.response;
  } catch (error) {
    console.error(`${endpoint}操作失败:`, error);
    throw error;
  }
};

// ==================== 项目相关方法 ====================

/**
 * 获取项目列表
 */
const getProject = async () => {
  try {
    // 修改数据来源为PanelSelection/WebProjectQuery
    const projects = await fetchData("PanelSelection/WebProjectQuery");
    projectList.value = projects.sort((a, b) => {
      if (a.id === 1) return -1;
      if (b.id === 1) return 1;
      return a.created_at - b.created_at;
    });

    // 优先使用本地保存的项目选择
    const savedProjectId = localStorage.getItem("selectedProjectId");
    if (savedProjectId) {
      const pid = Number(savedProjectId);
      if (projectList.value.find((p) => p.id === pid)) {
        selectedProjectId.value = pid;
        // 延迟调用由调用方决定是否 await
        await handleProjectChangeApp(pid);
        return;
      }
    }

    // 否则回退到默认项目（projectCode==='1'）
    const defaultProject = projectList.value.find((p) => p.projectCode === "1");
    if (defaultProject) {
      selectedProjectId.value = defaultProject.id;
      // 保持原来的加载行为
      handleProjectChangeApp(defaultProject.id);
    }
  } catch (error) {
    console.error("获取项目列表失败:", error);
    ElMessage.error("获取项目列表失败");
  }
};

/**
 * 打开复制面板对话框
 */
const copyPanelUnit = (row) => {
  copyPanelUnitRow.value = row;
  selectedCopyProjectId.value = null;
  selectedCopyProjectGuid.value = null;
  showCopyPanelDialog.value = true;
};

/**
 * 处理复制项目选择变化
 */
const handleCopyProjectChange = async (projectId) => {
  const selectedProject = projectList.value.find(
    (project) => project.id === projectId
  );
  if (selectedProject) {
    const webProject = await getWebProjectByHotelName(
      selectedProject.hotel_name
    );
    selectedCopyProjectGuid.value = webProject ? webProject.guid : null;
  } else {
    selectedCopyProjectGuid.value = null;
  }
};

/**
 * 确认复制面板
 */
const confirmCopyPanel = async () => {
  if (!selectedCopyProjectId.value) {
    ElMessage.warning("请选择目标项目");
    return;
  }

  if (!copyPanelUnitRow.value || !copyPanelUnitRow.value.guid) {
    ElMessage.error("无效的面板数据");
    return;
  }

  try {
    // 调用后端API复制面板
    const rs = await localHttp.post(
      "PanelSelection/CopyPanelUnitWithNewFields",
      {
        OriginalGuid: copyPanelUnitRow.value.guid,
        NewOwner: getCurrentUser(),
        NewProjectGuid: selectedCopyProjectGuid.value,
      }
    );

    if (rs.data.isok) {
      ElMessage.success("面板复制成功");
      showCopyPanelDialog.value = false;
      // 刷新面板单元列表
      //await loadPanelUnitsByProject(copyPanelUnitRow.value.project_guid);
    } else {
      ElMessage.error("面板复制失败: " + rs.data.message);
    }
  } catch (error) {
    console.error("复制面板失败:", error);
    ElMessage.error("复制面板失败");
  }
};

/**
 * 等待辅助函数: 轮询直到 predicate 返回 true 或超时
 */
const waitFor = async (predicate, timeout = 5000, interval = 100) => {
  const start = Date.now();
  while (true) {
    try {
      if (predicate()) return true;
    } catch (e) {
      // ignore
    }
    if (Date.now() - start > timeout) return false;
    await new Promise((r) => setTimeout(r, interval));
  }
};

const getSavedTreeNodeKey = () => {
  return (
    localStorage.getItem("selectedTreeNode") ||
    localStorage.getItem("selectedTreeNodeId") ||
    localStorage.getItem("selectedPanelNode") ||
    null
  );
};

const getTreeNodeDataByKey = (nodeKey) => {
  if (!nodeKey) return null;

  if (projectTree.value?.getNode) {
    const nodeInstance = projectTree.value.getNode(nodeKey);
    if (nodeInstance) {
      return nodeInstance.data || nodeInstance;
    }
  }

  const findNodeRecursively = (nodes) => {
    if (!nodes || nodes.length === 0) return null;
    for (const node of nodes) {
      if (node.id === nodeKey) return node;
      if (node.children && node.children.length) {
        const found = findNodeRecursively(node.children);
        if (found) return found;
      }
    }
    return null;
  };

  return findNodeRecursively(treeData.value || []);
};

const getPreferredTreeKey = () => {
  if (projectTree.value?.getCurrentKey) {
    const currentKey = projectTree.value.getCurrentKey();
    if (currentKey) {
      return currentKey;
    }
  }
  return getSavedTreeNodeKey();
};

const triggerCurrentTreeNodeClick = async (preferredKey = null) => {
  let nodeData = null;

  if (projectTree.value?.getCurrentNode && !preferredKey) {
    nodeData = projectTree.value.getCurrentNode();
  }

  if (!nodeData) {
    const key = preferredKey || getPreferredTreeKey();
    nodeData = getTreeNodeDataByKey(key);
  }

  if (nodeData) {
    await handleNodeClick(nodeData);
  }
};

const reloadTreeData = async () => {
  const preservedKey = getPreferredTreeKey();
  if (!selectedProjectId.value) {
    return preservedKey;
  }

  try {
    await handleProjectChangeApp(selectedProjectId.value);
    await waitFor(() => treeData.value && treeData.value.length > 0, 5000);
    await nextTick();

    if (preservedKey && projectTree.value?.setCurrentKey) {
      projectTree.value.setCurrentKey(preservedKey);
    }
  } catch (error) {
    console.error("重载项目树失败:", error);
  }

  return preservedKey;
};

/**
 * 从 localStorage 按顺序恢复用户的选择：
 * 1) selectedProjectId -> await handleProjectChangeApp
 * 2) 恢复 tree 选中节点
 * 3) 恢复 currentPanelUnit（并加载其配置）
 */
const restoreSelectionsFromLocalStorage = async () => {
  try {
    const savedProjectId = localStorage.getItem("selectedProjectId");
    const savedPanelUnit = localStorage.getItem("currentPanelUnit");
    const savedTreeNode = getSavedTreeNodeKey();

    // 1) 恢复项目并等待数据加载完成
    if (savedProjectId) {
      const pid = Number(savedProjectId);
      if (pid && pid !== selectedProjectId.value) {
        selectedProjectId.value = pid;
        await handleProjectChangeApp(pid);
      }
      const project = projectList.value.find((p) => p.id === pid);
      await GetProjectStatus(project.guid);
    }

    // 等待 treeData 已加载（至少有项目节点）和 unitTableData 已加载（无论长度）
    await waitFor(() => treeData.value && treeData.value.length > 0, 5000);

    // 2) 恢复树的选中节点（如果有）
    if (savedTreeNode && projectTree.value) {
      try {
        // 优先使用 el-tree 的 setCurrentKey 方法
        if (projectTree.value.setCurrentKey) {
          projectTree.value.setCurrentKey(savedTreeNode);
        }
        const treeNode = getTreeNodeDataByKey(savedTreeNode);
        if (treeNode) {
          await handleNodeClick(treeNode);
        }
      } catch (e) {
        console.warn("恢复树选中失败:", e);
      }
    }

    // 3) 恢复 currentPanelUnit（如果存在）
    if (savedPanelUnit) {
      // 等待面板单元列表加载完成
      await waitFor(() => Array.isArray(unitTableData.value), 5000);
      const unit = unitTableData.value.find((u) => u.guid === savedPanelUnit);
      if (unit) {
        // 使用行点击的加载逻辑，确保右侧面板配置加载完毕
        await handleUnitRowClick(unit);
      } else {
        // 如果找不到，尝试直接设置 GUID（容错）
        currentPanelUnit.value = savedPanelUnit;
      }
    }
  } catch (error) {
    console.error("恢复本地选择失败:", error);
  }
};

/**
 * Select 下拉显示时滚动到顶部
 */
const onSelectVisibleChange = (visible) => {
  if (visible) {
    nextTick(() => {
      const dropdown = document.querySelector(
        ".el-select-dropdown .el-select-dropdown__wrap"
      );
      if (dropdown) dropdown.scrollTop = 0;
    });
  }
};

/**
 * 选择器触发项目选择变化处理
 */
const handleProjectSelectorChange = async (projectId) => {
  // 清空其他相关数据
  mergedPanelUnitForm.value = [];
  singlePanelPatternPreview.value = "";
  singlePanelPreview.value = "";
  panelGroupPreview.value = "";
  currentPanelNode.value = null;
  panelConfigTable.value = [];
  panelGroupPreviewThumbnail.value = "";
  generationHistory.value = [];
  isProjectDownloadAvailable.value = false;

  // 调用原有的项目变更处理方法
  await handleProjectChangeApp(projectId);

  // 如果选择了项目，检查项目状态
  if (projectId) {
    const project = projectList.value.find((p) => p.id === projectId);
    if (project && project.guid) {
      // 检查项目状态
      const projectStatus = await GetProjectStatus(project.guid);

      // 如果项目正在生成，添加到轮询列表
      if (projectStatus === "生成中") {
        pollingItems.value.projects = pollingItems.value.projects || new Set();
        pollingItems.value.projects.add(project.guid);

        // 如果轮询未启动，启动轮询
        if (!isPollingActive.value) {
          startPolling();
        }
      }
    }
  }
};

/**
 * 项目选择变化处理
 */
const handleProjectChangeApp = async (projectId) => {
  treeData.value = [];
  unitTableData.value = []; // 清空面板单元列表

  if (!projectId) return;

  const project = projectList.value.find((p) => p.id === projectId);
  if (!project) return;
  let webProject = project;
  if (webProject.room_data_json === "[]") webProject = await createWebProjectRoomType(project);
  if (!webProject) {
    ElMessage.error(`项目 ${project.hotel_name} 数据初始化失败，跳过加载`);
    return;
  }
  const projectNode = await buildProjectTree(project, webProject);
  treeData.value = [projectNode];

  // 加载该项目对应的面板单元列表
  await loadPanelUnitsByProject(webProject.guid);
};

/**
 * 根据项目GUID加载面板单元列表
 */
const loadPanelUnitsByProject = async (projectGuid) => {
  try {
    const units = await localHttp.post(
      "PanelSelection/WebPanelUnitQueryByProject",
      JSON.stringify({ GUID: projectGuid })
    );
    unitTableData.value = JSON.parse(units.data.response) || [];
  } catch (error) {
    console.error("加载面板单元列表失败:", error);
    unitTableData.value = [];
  }
};

/**
 * 根据酒店名称查询 Web 项目
 */
const getWebProjectByHotelName = async (hotelName) => {
  // 从projectList.value直接查找，而不是重新查询
  return projectList.value.find((p) => p.hotel_name === hotelName);
};

/**
 * 创建 Web 项目
 */
const createWebProjectRoomType = async (project) => {
  try {
    // 创建房型
    const roomGuids = [];
    for (let i = 0; i < project.room_type_count; i++) {
      const roomData = {
        room_name: `房型${i + 1}`,
        room_description: `自动创建的房型`,
        panel_group_count: "[]",
        remarks: "",
        creator: getCurrentUser(),
      };

      const roomGuid = await updateDatabase(
        "PanelSelection/WebRoomTypeAdd",
        roomData
      );
      if (roomGuid && roomGuid.length === 32) {
        roomGuids.push(roomGuid);
      }
    }

    // 更新项目信息
    const updatedProject = {
      ...project,
      room_data_json: JSON.stringify(roomGuids),
    };

    await updateDatabase("PanelSelection/WebProjectUpdate", updatedProject);
    return updatedProject;
  } catch (error) {
    console.error("创建Web项目失败:", error);
    ElMessage.error("创建项目数据失败");
    return null;
  }
};

// ==================== 树结构相关方法 ====================

/**
 * 构建项目树结构
 */
const buildProjectTree = async (project, webProject) => {
  const roomGuids = JSON.parse(webProject.room_data_json || "[]");
  const roomNodes = [];

  for (const roomGuid of roomGuids) {
    const roomInfo = await getRoomTypeInfoByGuid(roomGuid);
    if (roomInfo) {
      const panelNodes = [];
      const panelGroups = JSON.parse(roomInfo.panel_group_count || "[]");
      for (const panelGuid of panelGroups) {
        const panelInfo = await getPanelInfoByGuid(panelGuid);
        if (panelInfo) {
          panelNodes.push({
            id: `panel-${roomGuid}-${panelGuid}_${roomInfo.room_name}`,
            name: `${panelInfo.panel_list_name}（${panelInfo.gang_series.split("_")[0]
              } ${formatNameFront12(panelInfo.model_type) || "无模型"}）`,
            type: "panel",
            roomGuid: roomGuid,
            panelGuid: panelGuid,
            panelInfo,
            projectId: project.id,
          });
        }
      }

      roomNodes.push({
        id: roomGuid,
        name: roomInfo.room_name,
        type: "room",
        projectId: project.id,
        webProjectId: webProject.id,
        roomGuid: roomGuid,
        children: panelNodes,
      });
    }
  }

  return {
    id: `project-${project.id}`,
    name: `${project.hotel_name} (${roomNodes.length})`,
    type: "project",
    project,
    webProject,
    children: roomNodes,
  };
};

/**
 * 根据GUID查询房型信息
 */
const getRoomTypeInfoByGuid = async (roomGuid) => {
  const rooms = await fetchData("PanelSelection/WebRoomTypeQuery");
  return rooms.find((r) => r.guid === roomGuid);
};

/**
 * 根据GUID查询面板组信息
 */
const getPanelInfoByGuid = async (panelGuid) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/WebPanelListQueryByGuid",
      JSON.stringify({ GUID: panelGuid })
    );
    return JSON.parse(rs.data.response)[0];
  } catch (error) {
    console.error("查询面板组失败:", error);
    return null;
  }
};

/**
 * 查找项目节点
 */
const findProjectNode = (projectId) => {
  if (!projectId || !treeData.value || treeData.value.length === 0) {
    return null;
  }
  return treeData.value.find((node) => node.id === `project-${projectId}`);
};

/**
 * 查找房型节点
 */
const findRoomNode = (projectId, roomGuid) =>
  findProjectNode(projectId)?.children.find((r) => r.roomGuid === roomGuid);

/**
 * 移除项目节点
 */
const removeProjectNode = (data) => {
  treeData.value = [];
  selectedProjectId.value = "";
};

/**
 * 树节点点击事件
 */
const handleNodeClick = async (data) => {
  // 持久化树的选中节点到 localStorage，便于下次恢复
  try {
    if (data && data.id) {
      localStorage.setItem("selectedTreeNode", data.id);
    }
  } catch (e) {
    // ignore
  }
  // 清空所有行的编辑状态
  panelConfigTable.value.forEach((item) => {
    item.isEditing = false;
  });

  // 保存当前的面板单元选择状态，以便在切换面板组后恢复
  const savedCurrentPanelUnit = currentPanelUnit.value;

  // 检查是否是切换到不同的面板组
  const isDifferentPanel =
    currentPanelNode.value &&
    data.type === "panel" &&
    currentPanelNode.value.panelGuid !== data.panelGuid;

  // 只有切换到不同的面板组时才清空右侧配置表格，但不清空面板单元数据
  if (isDifferentPanel || data.type !== "panel") {
    // 清空右侧配置表格
    panelConfigTable.value = [];
    patternsList.value = [];
    // 不清空currentPanelUnit.value，保留用户的选择状态
    // currentPanelUnit.value = null;  // 注释掉这行，保留选择状态
    //panelUnitForm.value = [];
  }

  if (data.type === "panel") {
    currentPanelNode.value = data;
    await loadPanelConfiguration(data);

    // 如果是切换到不同的面板组，尝试恢复之前选中的面板单元
    if (isDifferentPanel && savedCurrentPanelUnit) {
      // 检查之前选中的面板单元是否仍然存在于当前项目的面板单元列表中
      const unitExists = unitTableData.value.some(
        (unit) => unit.guid === savedCurrentPanelUnit
      );
      if (unitExists) {
        currentPanelUnit.value = savedCurrentPanelUnit;
      }
    }
  } else {
    currentPanelNode.value = null;
  }
};

// ==================== 房型相关方法 ====================

/**
 * 编辑房型名称
 */
const editRoomName = async (data) => {
  try {
    const { value: newName } = await ElMessageBox.prompt(
      "请输入新的房型名称",
      "修改房型名称",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputValue: data.name,
        inputPattern: /.+/,
        inputErrorMessage: "房型名称不能为空",
      }
    );

    const roomInfo = await getRoomTypeInfoByGuid(data.roomGuid);
    if (roomInfo) {
      await updateDatabase("PanelSelection/WebRoomTypeUpdate", {
        ...roomInfo,
        room_name: newName,
      });
      data.name = newName;
      ElMessage.success("房型名称修改成功");
    }
  } catch (err) {
    if (err !== "cancel") ElMessage.error("修改房型名称失败");
  }
};

/**
 * 新增房型
 */
const addRoomType = async (data) => {
  try {
    const { value: roomName } = await ElMessageBox.prompt(
      "请输入新房型名称",
      "新增房型",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputPattern: /.+/,
        inputErrorMessage: "房型名称不能为空",
      }
    );

    const projectNode = findProjectNode(data.project.id);
    if (!projectNode) return;

    // 创建新房型
    const roomData = {
      room_name: roomName,
      room_description: `手动创建的房型`,
      panel_group_count: "[]",
      remarks: "手动创建",
      creator: getCurrentUser(),
      project_id: projectNode.webProject.id,
    };

    const newRoomGuid = await updateDatabase(
      "PanelSelection/WebRoomTypeAdd",
      roomData
    );

    // 更新项目信息
    const roomGuids = JSON.parse(projectNode.webProject.room_data_json || "[]");
    roomGuids.push(newRoomGuid);

    const updatedProject = {
      ...projectNode.webProject,
      room_type_count: roomGuids.length,
      room_data_json: JSON.stringify(roomGuids),
    };

    await updateDatabase("PanelSelection/WebProjectUpdate", updatedProject);

    // 更新本地数据
    projectNode.webProject = updatedProject;
    projectNode.name = `${data.project.hotel_name} (${roomGuids.length})`;

    // 添加新节点
    projectNode.children.push({
      id: newRoomGuid,
      name: roomName,
      type: "room",
      projectId: data.project.id,
      webProjectId: projectNode.webProject.id,
      roomGuid: newRoomGuid,
      children: [],
    });

    ElMessage.success("房型新增成功");
  } catch (err) {
    if (err !== "cancel") ElMessage.error("新增房型失败: " + err.message);
  }
};

/**
 * 删除房型
 */
const deleteRoom = async (data) => {
  try {
    await ElMessageBox.confirm(
      "确定要删除这个房型吗？此操作将从数据库中删除，且不可恢复。",
      "确认删除",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
    );

    const projectNode = findProjectNode(data.projectId);
    if (!projectNode) return;

    // 删除房型
    await updateDatabase("PanelSelection/WebRoomTypeDelete", data.guid);

    // 更新项目信息
    const roomGuids = JSON.parse(projectNode.webProject.room_data_json || "[]");
    const updatedRoomGuids = roomGuids.filter((guid) => guid !== data.roomGuid);

    const updatedProject = {
      ...projectNode.webProject,
      room_type_count: updatedRoomGuids.length,
      room_data_json: JSON.stringify(updatedRoomGuids),
    };

    await updateDatabase("PanelSelection/WebProjectUpdate", updatedProject);

    // 更新本地数据
    projectNode.webProject = updatedProject;
    projectNode.name = `${data.project.hotel_name} (${updatedRoomGuids.length})`;

    // 删除节点
    const roomIndex = projectNode.children.findIndex(
      (r) => r.roomGuid === data.roomGuid
    );
    if (roomIndex !== -1) {
      projectNode.children.splice(roomIndex, 1);
      ElMessage.success("房型删除成功");
    }
  } catch (err) {
    if (err !== "cancel") ElMessage.error("删除房型失败");
  }
};

// ==================== 面板组相关方法 ====================
const CheckPanelGroup = (panelGroup) => {
  if (!panelGroup || !panelGroup.panel_group_count) {
    ElMessage.error("面板组数据无效");
    return false;
  }
  return true;
}
/**
 * 清空项目预览总图
 */
const SetProjectCdr = async () => {
  // 获取项目信息以获取GUID
  const projectNode = findProjectNode(selectedProjectId.value);
  if (
    !projectNode ||
    !projectNode.webProject ||
    !projectNode.webProject.guid
  ) {
    return null;
  }
  const response = await fetchData("PanelSelection/SetProjectUpdateCdr",
    { GUID: projectNode.webProject.guid});

  if (!response) {
    throw new Error(`操作失败: ${response.statusText}`);
  }
}
/**
 * 判断后台是否正在处理当前项目
 */
const GetProjectStatus = async (projectGuid = null) => {
  //console.log(projectGuid);
  // 获取项目信息以获取GUID
  let guidToUse = projectGuid;
  if (!guidToUse) {
    const projectNode = findProjectNode(selectedProjectId.value);
    if (
      !projectNode ||
      !projectNode.webProject ||
      !projectNode.webProject.guid
    ) {
      return null;
    }
    guidToUse = projectNode.webProject.guid;
  }

  const response = await fetchData("PanelSelection/GetWebProject",
    { GUID: guidToUse, UserName: getCurrentUser() });

  if (!response) {
    throw new Error(`操作失败: ${response.statusText}`);
  } else {
    // 检查cdr_filename是否为空，以确定下载按钮是否可用
    isProjectDownloadAvailable.value = response[0].cdr_filename !== null && response[0].cdr_filename !== "";
    // 返回项目状态
    return response[0].edit_status;
  }
}
/**
 * 发送项目CDR地址到后台制图工具
 */
const GetAllProjectCDR = async () => {
  // 点击按钮时：弹出参数窗口，并回填历史填写的数据
  const projectNode = findProjectNode(selectedProjectId.value);
  if (!projectNode || !projectNode.webProject || !projectNode.webProject.guid) {
    ElMessage.error("无法获取项目GUID");
    return;
  }

  if (!Array.isArray(fontList.value) || fontList.value.length === 0) {
    await getFont();
  }
  await loadProjectCdrEnums();

  const projectGuid = projectNode.webProject.guid;
  projectCdrGuid.value = projectGuid;
  projectCdrProjectName.value = projectNode.webProject.hotel_name || "";

  // 先从数据库回填（后端已将这些字段写入 tbl_web_project）
  const webProject = await fetchData("PanelSelection/GetWebProject", {
    GUID: projectGuid,
    UserName: getCurrentUser(),
  });
  if (Array.isArray(webProject) && webProject.length > 0) {
    applyProjectCdrParamsFromWebProject(webProject[0]);
  }

  // 再从本地缓存回填（如果用户之前填写过）
  loadProjectCdrParams(projectGuid);

  ensureProjectCdrDefaults();

  showProjectCdrDialog.value = true;
};

const confirmProjectCdr = async () => {
  if (!projectCdrGuid.value) {
    ElMessage.error("无法获取项目GUID");
    return;
  }
  ensureProjectCdrDefaults();
  saveProjectCdrParams(projectCdrGuid.value);
  showProjectCdrDialog.value = false;
  await submitGetAllProjectCDR();
};

const submitGetAllProjectCDR = async () => {
  // 获取项目信息以获取GUID
  const projectNode = findProjectNode(selectedProjectId.value);
  if (!projectNode || !projectNode.webProject || !projectNode.webProject.guid) {
    ElMessage.error("无法获取项目GUID");
    return;
  }

  const startTime = new Date();
  const projectGuid = projectNode.webProject.guid;
  const projectName = projectNode.webProject.hotel_name;

  // 创建生成中记录
  const record = {
    guid: projectGuid,
    name: projectName,
    type: GenerationType.PROJECT,
    status: GenerationStatus.IN_PROGRESS,
    progress: 0,
    progressText: "正在生成项目总览图...",
    createdAt: formatDate(startTime),
    startTime: startTime.getTime(),
    completedAt: null,
    duration: null,
  };

  // 检查是否有同名且状态为"生成中"的项目记录，如果有则将其标记为"已取消"
  const existingRecordIndex = generationHistory.value.findIndex(
    (item) => item.name === record.name && item.type === GenerationType.PROJECT && item.status === GenerationStatus.IN_PROGRESS
  );
  if (existingRecordIndex !== -1) {
    generationHistory.value[existingRecordIndex].status = GenerationStatus.CANCELLED;
  }

  // 添加到生成历史
  generationHistory.value.unshift(record);
  isProjectGenerating.value = true;

  // 添加到轮询项目列表
  pollingItems.value.projects = pollingItems.value.projects || new Set();
  pollingItems.value.projects.add(projectGuid);

  // 调用后端API（补齐后端要求的新参数；ProjectName 不需要用户输入）
  await fetchData("PanelSelection/GetAllProjectCDR", {
    GUID: projectGuid,
    UserName: getCurrentUser(),
    Protocol: projectCdrForm.value.Protocol,
    ProjectName: projectName,
    SwitchSeries: projectCdrForm.value.SwitchSeries,
    SocketSeries: projectCdrForm.value.SocketSeries === "无" ? "" : projectCdrForm.value.SocketSeries,
    ChineseFont: projectCdrForm.value.ChineseFont,
    ChineseFontSize: projectCdrForm.value.ChineseFontSize,
    EnglishFont: projectCdrForm.value.EnglishFont,
    EnglishFontSize: projectCdrForm.value.EnglishFontSize,
  });

  // 如果轮询未启动，启动轮询
  if (!isPollingActive.value) {
    startPolling();
  }
};
/**
 * 下载项目所有PLT、CDR和PNG文件并打包为ZIP
 */
const DownloadProjectCDR = async () => {
  try {
    // 获取项目信息以获取GUID
    const projectNode = findProjectNode(selectedProjectId.value);
    if (
      !projectNode ||
      !projectNode.webProject ||
      !projectNode.webProject.guid
    ) {
      ElMessage.error("无法获取项目GUID");
      return;
    }

    const loading = ElLoading.service({ text: "正在准备下载文件..." });

    // 调用后端API获取ZIP文件
    const response = await fetch(`${config.ApiList[1]}PanelSelection/DownloadProjectCDR`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ GUID: projectNode.webProject.guid, UserName: getCurrentUser() })
    });

    if (!response.ok) {
      throw new Error(`下载失败: ${response.statusText}`);
    }

    // 获取文件内容
    const blob = await response.blob();

    // 生成带日期时间的文件名
    const now = new Date();
    const dateStr = now.getFullYear() +
      String(now.getMonth() + 1).padStart(2, '0') +
      String(now.getDate()).padStart(2, '0');
    const timeStr = String(now.getHours()).padStart(2, '0') +
      String(now.getMinutes()).padStart(2, '0') +
      String(now.getSeconds()).padStart(2, '0');

    const fileName = `${projectNode.webProject.hotel_name}_${dateStr}_${timeStr}.zip`;

    // 创建下载链接并触发下载
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = fileName;
    document.body.appendChild(link);
    link.click();

    // 清理
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);

    loading.close();
    ElMessage.success("文件下载成功");
  } catch (error) {
    console.error("下载文件失败:", error);
    ElMessage.error(`下载失败: ${error.message}`);
  }
}
/**
 * 下载项目所有PLT、CDR和PNG文件并打包为ZIP
 */
const downloadProjectPLTFiles = async () => {
  if (!selectedProjectId.value) {
    ElMessage.warning("请先选择项目");
    return;
  }

  try {
    const loading = ElLoading.service({ text: "正在准备下载文件..." });

    // 获取项目信息以获取GUID
    const projectNode = findProjectNode(selectedProjectId.value);
    if (
      !projectNode ||
      !projectNode.webProject ||
      !projectNode.webProject.guid
    ) {
      ElMessage.error("无法获取项目GUID");
      loading.close();
      return;
    }

    // 调用GetWebProjectCDR方法获取地址数组
    const projects = await fetchData("PanelSelection/GetWebProjectCDR", {
      GUID: projectNode.webProject.guid,
    });
    console.log(projects);
    if (!projects || !Array.isArray(projects)) {
      ElMessage.error("获取文件地址失败");
      loading.close();
      return;
    }
    // 检查所有面板组的cdr_filename是否为空
    const hasEmptyCdrFilename = projects.some(address => !address.cdr_filename);
    if (hasEmptyCdrFilename) {
      ElMessage.warning("当前项目还有未生成的面板组");
      loading.close();
      return;
    }

    // 创建JSZip实例
    const zip = new JSZip();

    // 创建PLT和CDR文件夹
    const pltFolder = zip.folder("PLT");
    const cdrFolder = zip.folder("CDR");

    let pltFilesAdded = 0;
    let cdrFilesAdded = 0;
    let pngFilesAdded = 0;
    const totalFiles = projects.length;

    if (totalFiles === 0) {
      ElMessage.warning("当前项目没有可下载的文件");
      loading.close();
      return;
    }

    // 更新loading文本
    loading.setText(`正在下载PLT文件... 0/${totalFiles}`);

    // 下载所有PLT文件并添加到zip的PLT文件夹
    const pltDownloadPromises = projects.map(async (address) => {
      try {
        // 添加config.PicAds前缀
        const fullUrl = `${config.PicAds}${address.cdr_filename}`;

        // 使用fetch下载文件
        const response = await fetch(fullUrl);
        if (!response.ok) {
          throw new Error(`下载PLT文件失败: ${address.cdr_filename}`);
        }

        // 获取文件内容
        const blob = await response.blob();
        // 从地址中提取文件名，确保只保留文件名部分，不包含任何路径信息
        const fileName = `数量${address.carving_quantity}_${projectNode.webProject.hotel_name}_${address.room_name
          }_${address.panel_list_name}_${address.gang_series || "未知系列"
          }_${formatNameFront12(address.model_type)}_${formatDate1(new Date())}.plt`;

        // 将文件添加到ZIP的PLT文件夹
        pltFolder.file(fileName, blob);

        pltFilesAdded++;
        loading.setText(`正在下载PLT文件... ${pltFilesAdded}/${totalFiles}`);
      } catch (error) {
        console.error("下载单个PLT文件失败:", error);
        // 继续尝试下载其他文件
      }
    });

    // 等待所有PLT文件下载完成
    await Promise.all(pltDownloadPromises);

    // 更新loading文本，开始下载CDR文件
    loading.setText(`正在下载CDR文件... 0/${totalFiles}`);

    // 下载所有CDR文件并添加到zip的CDR文件夹
    const cdrDownloadPromises = projects.map(async (address) => {
      try {
        // 将路径最后3个字符"plt"修改为"cdr"
        let cdrPath = address.cdr_filename;
        if (cdrPath.length >= 3 && cdrPath.substring(cdrPath.length - 3).toLowerCase() === 'plt') {
          cdrPath = cdrPath.substring(0, cdrPath.length - 3) + 'cdr';
        }

        // 添加config.PicAds前缀
        const fullUrl = `${config.PicAds}${cdrPath}`;

        // 使用fetch下载文件
        const response = await fetch(fullUrl);
        if (!response.ok) {
          throw new Error(`下载CDR文件失败: ${cdrPath}`);
        }

        // 获取文件内容
        const blob = await response.blob();
        //console.log(address);
        // 从地址中提取文件名，确保只保留文件名部分，不包含任何路径信息
        const fileName = `数量${address.carving_quantity}_${projectNode.webProject.hotel_name}_${address.room_name
          }_${address.panel_list_name}_${address.gang_series || "未知系列"
          }_${formatNameFront12(address.model_type)}_${formatDate1(new Date())}.cdr`;

        // 将文件添加到ZIP的CDR文件夹
        cdrFolder.file(fileName, blob);

        cdrFilesAdded++;
        loading.setText(`正在下载CDR文件... ${cdrFilesAdded}/${totalFiles}`);
      } catch (error) {
        console.error("下载单个CDR文件失败:", error);
        // 继续尝试下载其他文件
      }
    });

    // 等待所有CDR文件下载完成
    await Promise.all(cdrDownloadPromises);

    // 更新loading文本，开始下载PNG文件
    loading.setText(`正在下载PNG文件... 0/${totalFiles}`);

    // 下载所有PNG文件并添加到zip的PNG文件夹
    const pngDownloadPromises = projects.map(async (address) => {
      try {
        // 检查thumbnail_large是否存在
        if (!address.thumbnail_large) {
          console.warn(address, "PNG文件路径不存在，跳过下载");
          return;
        }

        // 添加config.PicAds前缀
        const fullUrl = `${config.PicAds}${address.thumbnail_large}`;

        // 使用fetch下载文件
        const response = await fetch(fullUrl);
        if (!response.ok) {
          throw new Error(`下载PNG文件失败: ${address.thumbnail_large}`);
        }

        // 获取文件内容
        const blob = await response.blob();

        // 使用与PLT文件相同的命名规则，但后缀为.png
        const fileName = `数量${address.carving_quantity}_${projectNode.webProject.hotel_name}_${address.room_name
          }_${address.panel_list_name}_${address.gang_series || "未知系列"
          }_${formatNameFront12(address.model_type)}_${formatDate1(new Date())}.png`;

        // 将文件添加到ZIP的PLT文件夹
        pltFolder.file(fileName, blob);

        pngFilesAdded++;
        loading.setText(`正在下载PNG文件... ${pngFilesAdded}/${totalFiles}`);
      } catch (error) {
        console.error("下载单个PNG文件失败:", error);
        // 继续尝试下载其他文件
      }
    });

    // 等待所有PNG文件下载完成
    await Promise.all(pngDownloadPromises);

    // 检查是否有文件下载成功
    if (pltFilesAdded === 0 && cdrFilesAdded === 0 && pngFilesAdded === 0) {
      ElMessage.error("所有文件下载失败");
      loading.close();
      return;
    }

    // 生成zip文件
    loading.setText("正在生成ZIP文件...");
    const zipBlob = await zip.generateAsync({ type: "blob" });

    // 创建下载链接
    const link = document.createElement("a");
    link.href = URL.createObjectURL(zipBlob);
    link.download = `${projectNode.webProject.hotel_name || "未知酒店"}_${formatDate2(new Date())}.zip`;
    document.body.appendChild(link);
    link.click();

    // 清理
    document.body.removeChild(link);
    URL.revokeObjectURL(link.href);

    loading.close();

    // 显示下载结果
    let successMessage = `成功下载 `;
    const fileTypes = [];

    if (pltFilesAdded > 0) {
      fileTypes.push(`${pltFilesAdded}/${totalFiles} 个PLT文件`);
    }
    if (cdrFilesAdded > 0) {
      fileTypes.push(`${cdrFilesAdded}/${totalFiles} 个CDR文件`);
    }
    if (pngFilesAdded > 0) {
      fileTypes.push(`${pngFilesAdded}/${totalFiles} 个PNG文件`);
    }

    successMessage += fileTypes.join("，");

    ElMessage.success(successMessage);
  } catch (error) {
    console.error("下载项目文件失败:", error);
    ElMessage.error("下载失败，请稍后重试");
  }
};

/**
 * 处理面板单元选择变化
 */
const handlePanelUnitChange = async (index, panelUnitGuid) => {
  console.log(index, panelUnitGuid);
  const selectedUnit = availablePanelUnits.value.find(
    (unit) => unit.guid === panelUnitGuid
  );
  if (selectedUnit) {
    panelConfigTable.value[index].panelUnitData = selectedUnit;
    panelConfigTable.value[index].isEditing = false;

    // 更新单面板预览图
    //await updateSinglePanelPreviewFromUnit(selectedUnit);
    await clearPanelGroupPreview();
    // 保存面板配置
    await savePanelConfig();
    await SetProjectCdr();
  }
};

/**
 * 编辑面板单元配置
 */
const editPanelUnitConfig = (row) => {
  if (!row.panelUnitGuid) {
    //ElMessage.warning('请先选择面板单元');
    return;
  }

  const unit = availablePanelUnits.value.find(
    (u) => u.guid === row.panelUnitGuid
  );
  if (unit) {
    // 触发面板单元行点击事件，加载配置到右侧
    handleUnitRowClick(unit);

    // 标记当前正在编辑的面板配置行
    panelConfigTable.value.forEach((item) => {
      item.isEditing = false;
    });

    // 设置当前编辑的面板单元
    currentPanelUnit.value = row.panelUnitGuid;
  }
};

/**
 * 从面板单元数据更新单面板预览图
 */
const updateSinglePanelPreviewFromUnit = async (panelUnit) => {
  if (!panelUnit) {
    singlePanelPreview.value = "";
    return;
  }

  if (panelUnit.thumbnail_large) {
    singlePanelPreview.value = config.PicAds + panelUnit.thumbnail_large;
  } else {
    singlePanelPreview.value = "";
  }
};
/**
 * 添加面板组
 */
const addPanel = async (data) => {
  currentRoomData.value = data;
  resetPanelDialog();
  showAddPanelDialog.value = true;
};

/**
 * 编辑面板组名称
 */
const editPanelName = async (data) => {
  try {
    const panelInfo = await getPanelInfoByGuid(data.panelGuid);
    if (panelInfo) {
      currentRoomData.value = data;
      newPanelForm.value = {
        panel_list_name: panelInfo.panel_list_name,
        gang_series: panelInfo.gang_series,
        model_type: panelInfo.model_type || "",
        panel_count: panelInfo.panel_count || null,
        gang_material_id: panelInfo.gang_material_id || 0,
        remarks: panelInfo.remarks || "",
        logo_json: panelInfo.logo_json || "",
        carving_quantity: panelInfo.carving_quantity || null,
        position: panelInfo.position || "",
      };

      // 解析系列信息
      const [seriesName, version] = panelInfo.gang_series.split("_");
      const matchedSeries = seriesList.value.find(
        (item) => item.Series === seriesName && item.Version === version
      );

      if (matchedSeries) {
        selectedSeries.value = matchedSeries;
        await getModels(matchedSeries.ID);

        if (panelInfo.model_type) {
          let matchedModel = allModels.value.find(
            (model) => model.ModelName === panelInfo.model_type
          );

          if (!matchedModel && panelInfo.gang_material_id) {
            matchedModel = allModels.value.find(
              (model) => model.ID === panelInfo.gang_material_id
            );
          }

          if (matchedModel) {
            selectedPanelCount.value = matchedModel.PanelCount;
            selectedDirection.value = matchedModel.Direction;
            selectedColor.value = matchedModel.Color;
            updateModelList();
            selectedModel.value = matchedModel;
            newPanelForm.value.model_type = matchedModel.ModelName;

            await restoreLogoConfig(panelInfo);
          } else {
            newPanelForm.value.model_type = panelInfo.model_type;
            // 即使没有匹配模型也尝试恢复LOGO配置
            await restoreLogoConfig(panelInfo);
          }
        } else {
          // 如果没有模型类型，也尝试恢复LOGO配置
          await restoreLogoConfig(panelInfo);
        }
      }

      editingPanelGuid.value = data.panelGuid;
      showAddPanelDialog.value = true;
    }
  } catch (error) {
    console.error("获取面板组信息失败:", error);
    ElMessage.error("获取面板组信息失败");
  }
};

/**
 * 删除面板组
 */
const deletePanel = async (data) => {
  try {
    await ElMessageBox.confirm(
      "确定要删除这个面板组吗？此操作将从数据库中删除，且不可恢复。",
      "确认删除",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
    );

    const roomNode = findRoomNode(data.projectId, data.roomGuid);
    if (!roomNode) return;

    // 从房型中移除面板组
    await removePanelFromRoomGroups(data.roomGuid, data.panelGuid);

    // 删除面板组
    await updateDatabase("PanelSelection/WebPanelListDelete", data.panelGuid);

    // 更新树结构
    const panelIndex = roomNode.children.findIndex(
      (p) => p.panelGuid === data.panelGuid
    );
    if (panelIndex !== -1) {
      roomNode.children.splice(panelIndex, 1);
      ElMessage.success("面板组删除成功");
    }
  } catch (err) {
    if (err !== "cancel") ElMessage.error("删除面板组失败");
  }
};

/**
 * 从房型中移除面板组
 */
const removePanelFromRoomGroups = async (roomGuid, panelGuid) => {
  const roomInfo = await getRoomTypeInfoByGuid(roomGuid);
  if (!roomInfo) return;

  const panelGroups = JSON.parse(roomInfo.panel_group_count || "[]");
  const updatedPanelGroups = panelGroups.filter((guid) => guid !== panelGuid);

  await updateDatabase("PanelSelection/WebRoomTypeUpdate", {
    ...roomInfo,
    panel_group_count: JSON.stringify(updatedPanelGroups),
  });
};

// ==================== 面板组对话框相关方法 ====================

/**
 * 获取模型数据
 */
const getModels = async (fileId) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/ModelQuery",
      JSON.stringify({ FID: fileId })
    );
    if (rs.data.isok && rs.data.response) {
      allModels.value = JSON.parse(rs.data.response);

      panelCountOptions.value = [
        ...new Set(allModels.value.map((model) => model.PanelCount)),
      ].sort();
      directionOptions.value = [
        ...new Set(allModels.value.map((model) => model.Direction)),
      ];
      colorOptions.value = [
        ...new Set(allModels.value.map((model) => model.Color)),
      ];
    } else {
      allModels.value = [];
    }
  } catch (error) {
    console.error("获取模型列表失败:", error);
    allModels.value = [];
    ElMessage.error("获取模型列表失败");
  }
};

/**
 * 更新模型列表
 */
const updateModelList = () => {
  if (
    !selectedPanelCount.value ||
    !selectedDirection.value ||
    !selectedColor.value
  ) {
    filteredModels.value = [];
    selectedModel.value = null;
    newPanelForm.value.model_type = "";
    return;
  }

  filteredModels.value = allModels.value.filter((model) => {
    return (
      model.PanelCount == selectedPanelCount.value &&
      model.Direction === selectedDirection.value &&
      model.Color === selectedColor.value
    );
  });

  if (filteredModels.value.length === 1) {
    selectedModel.value = filteredModels.value[0];
    newPanelForm.value.model_type = selectedModel.value.ModelName;
    selectedSeriesPreview.value = config.PicAds + selectedModel.value.PreviewPath;
  } else {
    selectedModel.value = null;
    newPanelForm.value.model_type = "";
  }
};

/**
 * 系列选择变化处理
 */
const handleSeriesChange = async (currentRow) => {
  selectedSeries.value = currentRow;
  selectedModel.value = null;
  allModels.value = [];
  filteredModels.value = [];

  selectedPanelCount.value = "";
  selectedDirection.value = "";
  selectedColor.value = "";
  panelCountOptions.value = [];
  directionOptions.value = [];
  colorOptions.value = [];

  if (currentRow) {
    newPanelForm.value.gang_series = `${currentRow.Series}_${currentRow.Version}`;

    await getModels(currentRow.ID);
  } else {
    logoList.value = [];
    newPanelForm.value.gang_series = "";
    selectedSeriesPreview.value = "";
    logoConfig.value = {
      LogoPosition: "",
      LogoFileName: "",
      LogoIndexNumber: "",
    };
  }
};

/**
 * 确认添加/编辑面板组
 */
const confirmAddPanel = async () => {
  if (!newPanelForm.value.panel_list_name) {
    ElMessage.error("请填写面板组名称");
    return;
  }

  if (!selectedSeries.value) {
    ElMessage.error("请选择系列");
    return;
  }

  if (
    !selectedPanelCount.value ||
    !selectedDirection.value ||
    !selectedColor.value
  ) {
    ElMessage.error("请完整选择面板数、方向和颜色");
    return;
  }

  if (!selectedModel.value) {
    ElMessage.error("请选择模型");
    return;
  }
  let logoJsonValue = JSON.stringify(logoConfig.value);
  try {
    if (editingPanelGuid.value) {
      // 编辑模式
      const panelInfo = await getPanelInfoByGuid(editingPanelGuid.value);
      if (panelInfo) {
        await updateDatabase("PanelSelection/WebPanelListUpdate", {
          ...panelInfo,
          panel_list_name: newPanelForm.value.panel_list_name,
          gang_series: newPanelForm.value.gang_series,
          model_type: selectedModel.value.ModelName,
          gang_material_id: selectedModel.value.ID,
          remarks: newPanelForm.value.remarks,
          logo_json: logoJsonValue,
          carving_quantity: newPanelForm.value.carving_quantity,
          position: newPanelForm.value.position,
        });
        // 调用GetProjectStatus更新项目状态
        await GetProjectStatus();
        // 更新树节点
        const roomNode = findRoomNode(
          currentRoomData.value.projectId,
          currentRoomData.value.roomGuid
        );
        if (roomNode) {
          const panelNode = roomNode.children.find(
            (p) => p.panelGuid === editingPanelGuid.value
          );
          if (panelNode) {
            panelNode.name = `${newPanelForm.value.panel_list_name}（${newPanelForm.value.gang_series}）`;
            panelNode.panelInfo = {
              ...panelNode.panelInfo,
              ...newPanelForm.value,
              model_type: selectedModel.value.ModelName,
              gang_material_id: selectedModel.value.ID,
            };
          }
        }

        //ElMessage.success("面板组修改成功");
      }
    } else {
      // 新增模式
      const newPanelGuid = await createPanelInDatabase(newPanelForm.value);
      if (newPanelGuid) {
        await updateRoomPanelGroups(
          currentRoomData.value.roomGuid,
          newPanelGuid
        );

        // 添加新节点
        const roomNode = findRoomNode(
          currentRoomData.value.projectId,
          currentRoomData.value.roomGuid
        );
        if (roomNode) {
          const panelInfo = await getPanelInfoByGuid(newPanelGuid);
          if (panelInfo) {
            roomNode.children.push({
              id: `panel-${currentRoomData.value.roomGuid}-${newPanelGuid}`,
              name: `${panelInfo.panel_list_name}（${panelInfo.gang_series}）`,
              type: "panel",
              roomGuid: currentRoomData.value.roomGuid,
              panelGuid: newPanelGuid,
              panelInfo: {
                ...panelInfo,
                panel_info_json: '{"panels":[]}',
              },
              projectId: currentRoomData.value.projectId,
              gang_material_id: selectedModel.value.ID,
              logo_json: logoJsonValue,
            });
          }
        }
        ElMessage.success("面板组新增成功");
      }
    }

    showAddPanelDialog.value = false;
    resetPanelDialog();
  } catch (error) {
    console.error(
      editingPanelGuid.value ? "修改面板组失败:" : "新增面板组失败:",
      error
    );
    ElMessage.error(
      editingPanelGuid.value ? "修改面板组失败" : "新增面板组失败"
    );
  }
};

/**
 * 创建面板组
 */
const createPanelInDatabase = async (panelData) => {
  if (!selectedSeries.value || !selectedModel.value) {
    throw new Error("请先选择系列和模型");
  }
  const fullPanelData = {
    panel_list_name: panelData.panel_list_name,
    gang_series: panelData.gang_series,
    model_type: selectedModel.value.ModelName,
    panel_count: selectedModel.value.PanelCount,
    gang_material_id: selectedModel.value.ID,
    panel_info_json: '{"panelUnitGuids":[]}', // 初始化为空GUID数组
    logo_json: panelData.logo_json || "{}",
    cdr_filename: "",
    thumbnail_large: "",
    thumbnail_small: "",
    design_status: "",
    erp_part_number: "",
    remarks: panelData.remarks || "",
    room_type_id: 1,
    carving_quantity: panelData.carving_quantity,
    position: panelData.position,
  };

  return await updateDatabase("PanelSelection/WebPanelListAdd", fullPanelData);
};

/**
 * 更新房型面板组
 */
const updateRoomPanelGroups = async (roomGuid, panelGuid) => {
  const roomInfo = await getRoomTypeInfoByGuid(roomGuid);
  if (!roomInfo) {
    ElMessage.error("未找到对应的房型信息");
    return false;
  }

  const panelGroups = JSON.parse(roomInfo.panel_group_count || "[]");
  if (!panelGroups.includes(panelGuid)) {
    panelGroups.push(panelGuid);
    await updateDatabase("PanelSelection/WebRoomTypeUpdate", {
      ...roomInfo,
      panel_group_count: JSON.stringify(panelGroups),
    });
  }
  return true;
};

/**
 * 重置对话框
 */
const resetPanelDialog = () => {
  newPanelForm.value = {
    panel_list_name: "",
    gang_series: "",
    model_type: "",
    gang_material_id: 0,
    panel_count: null,
    remarks: "",
    logo_json: "{}",
    carving_quantity: null, // 新增雕刻数量字段
    position: "", // 新增位置字段
  };
  selectedSeries.value = null;
  selectedModel.value = null;
  allModels.value = [];
  filteredModels.value = [];
  selectedPanelCount.value = "";
  selectedDirection.value = "";
  selectedColor.value = "";
  panelCountOptions.value = [];
  directionOptions.value = [];
  colorOptions.value = [];
  editingPanelGuid.value = null;
  logoConfig.value = {
    LogoPosition: "",
    LogoFileName: "",
    LogoIndexNumber: "",
  };
};

// ==================== 面板配置相关方法 ====================
/**
 * 编辑面板单元
 */
const editPanelUnit = async (row) => {
  try {
    showLoading("加载面板单元数据中...");

    // 设置编辑模式
    isEditPanelUnit.value = true;
    currentEditPanelUnit.value = row;

    // 填充基本表单数据
    newPanelUnitForm.value = {
      panel_name: row.panel_name,
      remarks: row.remarks || "",
    };

    // 重置选择器
    selectedSeriesForUnit.value = null;
    selectedDirectionForUnit.value = "";
    selectedColorForUnit.value = "";
    selectedPatternForUnit.value = "";

    // 从面板单元数据中恢复之前的选择
    await restorePanelUnitSelections(row);

    // 打开对话框
    showAddPanelUnitDialog.value = true;

    hideLoading();
  } catch (error) {
    hideLoading();
    console.error("加载面板单元数据失败:", error);
    ElMessage.error("加载面板单元数据失败");
  }
};

/**
 * 从面板单元数据恢复选择信息
 */
const restorePanelUnitSelections = async (panelUnit) => {
  try {
    // 方法1: 使用新增的字段直接恢复选择
    if (panelUnit.series_id) {
      const series = seriesList.value.find((s) => s.ID === panelUnit.series_id);
      if (series) {
        selectedSeriesForUnit.value = series;
        return; // 后续由watch处理
      }
    }

    // 方法2: 从product_type中尝试匹配（最后的手段）
    if (panelUnit.product_type) {
      for (const series of seriesList.value) {
        if (
          panelUnit.product_type.includes(series.Series) ||
          panelUnit.product_type.includes(series.FileName)
        ) {
          selectedSeriesForUnit.value = series;
          return; // 后续由watch处理
        }
      }
    }
  } catch (error) {
    console.error("恢复面板单元选择信息失败:", error);
  }
};


/**
 * 加载面板配置
 */
const loadPanelConfiguration = async (panelNode) => {
  try {
    if (panelNode.panelInfo && panelNode.panelInfo.gang_material_id) {
      await getPatterns(panelNode.panelInfo.gang_material_id);
    }

    initPanelConfigTable(panelNode);

    //ElMessage.success('面板配置加载成功');
  } catch (error) {
    console.error("加载面板配置失败:", error);
    ElMessage.error("加载面板配置失败");
  }
};
/**
 * 删除面板单元
 */
const deletePanelUnit = async (row) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除面板单元 "${row.panel_name}" 吗？此操作不可恢复。`,
      "确认删除",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
    );

    // 调用后端删除API（实际上是更新is_valid为0）
    await updateDatabase("PanelSelection/WebPanelUnitDelete", row.guid);

    ElMessage.success("面板单元删除成功");

    // 刷新列表
    const projectNode = findProjectNode(selectedProjectId.value);
    if (projectNode?.webProject?.guid) {
      await loadPanelUnitsByProject(projectNode.webProject.guid);
    }

    // 如果删除的是当前正在编辑的面板单元，清空右侧配置
    if (currentPanelUnit.value === row.guid) {
      currentPanelUnit.value = null;
      panelUnitForm.value = [];
      singlePanelPreview.value = "";
    }
  } catch (error) {
    if (error !== "cancel") {
      console.error("删除面板单元失败:", error);
      ElMessage.error("删除面板单元失败");
    }
  }
};
/**
 * 初始化面板配置表格
 */
const initPanelConfigTable = (panelNode) => {
  const panelCount = panelNode.panelInfo.panel_count || 3;

  panelConfigTable.value = Array.from({ length: panelCount }, (_, index) => ({
    panelIndex: index + 1,
    panelUnitGuid: null,
    panelUnitData: null,
    isEditing: false,
  }));

  if (panelNode.panelInfo && panelNode.panelInfo.panel_info_json) {
    try {
      const savedConfig = JSON.parse(panelNode.panelInfo.panel_info_json);

      // 兼容新旧数据结构
      if (
        savedConfig.panelUnitGuids &&
        Array.isArray(savedConfig.panelUnitGuids)
      ) {
        // 新数据结构：GUID数组
        savedConfig.panelUnitGuids.forEach((guid, index) => {
          if (panelConfigTable.value[index] && guid) {
            panelConfigTable.value[index].panelUnitGuid = guid;

            // 查找对应的面板单元数据
            const unit = availablePanelUnits.value.find((u) => u.guid === guid);
            if (unit) {
              panelConfigTable.value[index].panelUnitData = unit;
            }
          }
        });
      } else if (savedConfig.panels && Array.isArray(savedConfig.panels)) {
        // 旧数据结构：兼容处理
        savedConfig.panels.forEach((panelConfig, index) => {
          if (panelConfigTable.value[index] && panelConfig.panelUnitGuid) {
            panelConfigTable.value[index].panelUnitGuid =
              panelConfig.panelUnitGuid;

            const unit = availablePanelUnits.value.find(
              (u) => u.guid === panelConfig.panelUnitGuid
            );
            if (unit) {
              panelConfigTable.value[index].panelUnitData = unit;
            }
          }
        });
      }
    } catch (error) {
      console.error("解析保存的配置失败:", error);
    }
  }
};

/**
 * 获取Pattern列表
 */
const getPatterns = async (fileId) => {
  try {
    patternsList.value = await fetchData("PanelSelection/PatternQuery", {
      FID: fileId,
    });
  } catch (error) {
    console.error("获取Pattern列表失败:", error);
    patternsList.value = [];
  }
};

/**
 * 编辑面板配置
 */
const editPanelConfig = async (index) => {
  try {
    const panelConfig = panelConfigTable.value[index];
    if (!panelConfig.selectedPattern) {
      ElMessage.warning("请先选择面板模式");
      return;
    }

    panelConfigTable.value.forEach((item, i) => {
      item.isEditing = i === index;
    });
    await updateSinglePanelPreview(panelConfig.selectedPattern);

    const pattern = patternsList.value.find(
      (p) => p.ID === panelConfig.selectedPattern
    );
    if (!pattern) {
      ElMessage.error("未找到对应的面板模式信息");
      return;
    }

    const locations = await getLocationls(panelConfig.selectedPattern);
    let panelUnitGuid = panelConfig.panelUnitGuid;

    if (!panelUnitGuid) {
      panelUnitGuid = await createPanelUnitIfNotExists(
        panelConfig,
        pattern,
        locations,
        index
      );
    }

    if (panelUnitGuid) {
      panelConfig.panelUnitGuid = panelUnitGuid;
      await savePanelConfig();
      await loadPanelUnitConfiguration(panelUnitGuid, locations);
      //ElMessage.success("面板配置编辑已启动");
    }
  } catch (error) {
    console.error("编辑面板配置失败:", error);
    ElMessage.error("编辑面板配置失败");
  }
};

/**
 * 检查并创建面板单元（如果不存在）
 */
const createPanelUnitIfNotExists = async (
  panelConfig,
  pattern,
  locations,
  index
) => {
  try {
    const existingPanelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQuery"
    );
    const expectedPanelName = `${currentPanelNode.value.panelInfo.panel_list_name
      }_面板${index + 1}`;

    let existingPanelUnit = existingPanelUnits.find(
      (p) => p.panel_name === expectedPanelName && p.is_valid
    );

    if (existingPanelUnit) {
      return existingPanelUnit.guid;
    } else {
      // 获取当前项目的GUID
      const projectNode = findProjectNode(currentPanelNode.value.projectId);
      if (!projectNode || !projectNode.webProject) {
        throw new Error("未找到项目信息");
      }

      const panelUnitData = {
        panel_name: expectedPanelName,
        product_type: pattern.PatternName,
        element_count: locations.length,
        elements_json: "[]",
        cdr_filename: "",
        thumbnail_large: "",
        thumbnail_small: "",
        remarks: `关联面板组: ${currentPanelNode.value.panelInfo.panel_list_name}`,
        erp_part_number: "",
        design_status: "",
        owner: getCurrentUser(),
        share_type: "",
        project_guid: projectNode.webProject.guid, // 新增项目关联
      };

      const newGuid = await createPanelUnit(panelUnitData);
      return newGuid;
    }
  } catch (error) {
    console.error("检查/创建面板单元失败:", error);
    throw error;
  }
};

/**
 * 保存面板配置
 */
const savePanelConfig = async () => {
  if (!currentPanelNode.value) {
    return;
  }

  try {
    // 构建GUID数组配置
    const configData = {
      panelUnitGuids: panelConfigTable.value
        .map((item) => item.panelUnitGuid)
        .filter((guid) => guid), // 只保留有效的GUID
    };

    const panelInfo = await getPanelInfoByGuid(
      currentPanelNode.value.panelGuid
    );
    if (panelInfo) {
      await updateDatabase("PanelSelection/WebPanelListUpdate", {
        ...panelInfo,
        panel_info_json: JSON.stringify(configData),
        // 取消gang_material_id的绑定
        //gang_material_id: 0
      });
      // 调用GetProjectStatus更新项目状态
      await GetProjectStatus();

      currentPanelNode.value.panelInfo.panel_info_json =
        JSON.stringify(configData);
      currentPanelNode.value.panelInfo.gang_material_id = 0;
    }
  } catch (error) {
    console.error("保存面板配置失败:", error);
    ElMessage.error("保存面板配置失败");
  }
};

/**
 * 生成预览图（面板组合）
 */
const showPreview = async (ProcessType) => {
  if (!currentPanelNode.value) {
    //ElMessage.warning('请先选择面板组');
    return;
  }

  if (!isAllPanelsConfigured.value) {
    ElMessage.warning("请先完成所有面板的配置");
    return;
  }

  const startTime = performance.now();
  showLoading("生成预览图中...");

  try {
    // 从remark字段读取已保存的结构化数据
    const panelInfo = await getPanelInfoByGuid(
      currentPanelNode.value.panelGuid
    );
    let previewObject = null;

    // 如果没有从remark读取到，则重新生成
    if (!previewObject) {
      previewObject = await generatePanelGroupStructureData(true);
      if (previewObject) {
        previewObject.Process = ProcessType;
      }
    }

    if (!previewObject) {
      ElMessage.error("生成预览对象失败");
      hideLoading();
      return;
    }

    console.log("面板组预览对象:", previewObject);

    // 发送到CDR生成预览图
    const rs = await localHttp.post(
      "PanelSelection/SendToCDR",
      JSON.stringify(previewObject)
    );

    if (rs.data.isok) {
      const rsv = rs.data.response;

      if (rsv) {
        // 更新面板组信息
        if (panelInfo) {
          const updateData = {
            ...panelInfo,
            remarks: JSON.stringify({
              structureData: previewObject,
              savedAt: new Date().toISOString(),
              version: "1.0",
              lastGenerated: Date.now(),
            }),
          };
          // 图片生成
          updateData.design_status = "生成中";

          await updateDatabase("PanelSelection/WebPanelListUpdate", updateData);
            // 调用GetProjectStatus更新项目状态
            await GetProjectStatus();
        }

        // 添加生成记录到历史
        const project = projectList.value.find(
          (p) => p.id === selectedProjectId.value
        );
        const startTime = new Date();
        if (ProcessType == 0) {
          const record = {
            id: Date.now() + Math.random().toString(36).substr(2, 9),
            guid: currentPanelNode.value.panelGuid,
            name: `${project?.hotel_name || ""}_${currentPanelNode.value.panelInfo.panel_list_name || ""
              }`,
            type: GenerationType.PREVIEW,
            status: GenerationStatus.IN_PROGRESS,
            progress: 0,
            progressText: "正在生成预览图...",
            createdAt: formatDate(startTime),
            startTime: startTime.getTime(),
            completedAt: null,
            duration: null,
          };
          // 检查是否有同名且状态为"生成中"的记录，如果有则将其标记为"已取消"
          const existingRecordIndex = generationHistory.value.findIndex(
            item => item.name === record.name && item.status === GenerationStatus.IN_PROGRESS
          );
          if (existingRecordIndex !== -1) {
            generationHistory.value[existingRecordIndex].status = GenerationStatus.CANCELLED;
          }

          generationHistory.value.unshift(record);
          pollingItems.value.panelLists.add(record.guid);

        }

        if (!isPollingActive.value) {
          startPolling();
        }
      } else {
        ElMessage.error("面板设计图生成失败: " + rsv.Msg);
      }
    } else {
      ElMessage.error("面板设计图生成失败");
    }
  } catch (error) {
    console.error("生成面板组预览对象失败:", error);
    ElMessage.error("生成面板组预览对象失败: " + error.message);
  } finally {
    if (ProcessType == 0) {
      ElMessage.success("设计图已经加入生成队列，请稍后！");
      await showPreview(1);
    } else {
      hideLoading();
      // 保存当前选中的面板单元，以便在重新加载后恢复
      const savedCurrentPanelUnit = currentPanelUnit.value;
      await triggerCurrentTreeNodeClick();
      // 恢复之前选中的面板单元
      if (savedCurrentPanelUnit) {
        currentPanelUnit.value = savedCurrentPanelUnit;
      }
    }

  }
};
/**
 * 生成预览图（单个面板）
 */
const showSinglePanelPreview = async () => {
  if (!currentPanelUnit.value) {
    //ElMessage.warning('请先选择面板单元');
    return;
  }

  const startTime = performance.now();
  showLoading("生成单个面板预览图中...");

  try {
    // 从remark字段读取已保存的previewObject
    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: currentPanelUnit.value }
    );
    const panelUnit = panelUnits[0];
    let previewObject = null;

    // 如果没有从remark读取到，则重新生成
    if (!previewObject) {
      previewObject = await generateSinglePanelPreviewObject(true);
      if (previewObject) {
        //console.log("重新生成单个面板预览对象成功");
      }
    }

    if (!previewObject) {
      ElMessage.error("生成预览对象失败");
      hideLoading();
      return;
    }

    console.log("单个面板预览对象:", previewObject);

    // 发送到CDR生成预览图
    const rs = await localHttp.post(
      "PanelSelection/SendToCDR",
      JSON.stringify(previewObject)
    );

    if (rs.data.isok) {
      const rsv = rs.data.response;
      if (rsv) {
        // 将生成的完整previewObject保存到remark字段
        try {
          const saveData = {
            ...panelUnit,
            design_status: "生成中",
            remarks: JSON.stringify({
              previewObject: previewObject,
              savedAt: new Date().toISOString(),
              version: "1.0",
              lastGenerated: Date.now(),
            }),
          };
          // 保存到数据库
        await updateDatabase("PanelSelection/WebPanelUnitUpdate", saveData);
        // 调用GetProjectStatus更新项目状态
        await GetProjectStatus();
        } catch (saveError) {
          console.error("保存单个面板预览对象到remark字段失败:", saveError);
        }
        // 添加生成记录到历史
        const project = projectList.value.find(
          (p) => p.id === selectedProjectId.value
        );
        const startTime = new Date();
        const record = {
          id: Date.now() + Math.random().toString(36).substr(2, 9),
          guid: currentPanelUnit.value,
          name: `${project?.hotel_name || ""}_${panelUnit.panel_name || ""}`,
          type: GenerationType.SINGLE_PANEL,
          status: GenerationStatus.IN_PROGRESS,
          progress: 0,
          progressText: "正在生成单个面板预览图...",
          createdAt: formatDate(startTime),
          startTime: startTime.getTime(),
          completedAt: null,
          duration: null,
        };
        // 检查是否有同名且状态为"生成中"的记录，如果有则将其标记为"已取消"
        const existingRecordIndex = generationHistory.value.findIndex(
          item => item.name === record.name && item.status === GenerationStatus.IN_PROGRESS
        );
        if (existingRecordIndex !== -1) {
          generationHistory.value[existingRecordIndex].status = GenerationStatus.CANCELLED;
        }
        generationHistory.value.unshift(record);

        // 更新本地数据
        const unitIndex = unitTableData.value.findIndex(
          (u) => u.guid === currentPanelUnit.value
        );
        if (unitIndex !== -1) {
          unitTableData.value[unitIndex].design_status = "生成中";
        }

        ElMessage.success("设计图已经加入生成队列，请稍后！");

        if (!isPollingActive.value) {
          startPolling();
        }
      } else {
        ElMessage.error("单个面板预览图生成失败: " + rsv.Msg);
      }
    } else {
      ElMessage.error("单个面板预览图生成失败");
    }
  } catch (error) {
    console.error("生成单个面板预览对象失败:", error);
    ElMessage.error("生成单个面板预览对象失败: " + error.message);
  } finally {
    hideLoading();
  }
};
// ==================== 面板单元配置相关方法 ====================
/**
 * 单个面板的pattern预览图
 */
const singlePanelPatternPreview = ref("");
watch(
  currentPanelUnit,
  async (newGuid) => {
    if (!newGuid) {
      singlePanelPatternPreview.value = "";
      return;
    }

    // 从 unitTableData 中查找当前面板单元
    const panelUnit = unitTableData.value.find((unit) => unit.guid === newGuid);
    if (!panelUnit || !panelUnit.pattern_id) {
      singlePanelPatternPreview.value = "";
      return;
    }

    try {
      // 异步获取 pattern 数据
      const pattern = await fetchData("PanelSelection/IdPatternQuery", {
        FID: panelUnit.pattern_id,
      });
      if (pattern && pattern[0] && pattern[0].PreviewPath) {
        singlePanelPatternPreview.value =
          config.PicAds + pattern[0].PreviewPath;
      } else {
        singlePanelPatternPreview.value = "";
      }
    } catch (error) {
      singlePanelPatternPreview.value = "";
    }
  },
  { immediate: true }
);

/**
 * 创建面板单元
 */
const createPanelUnit = async (panelUnitData) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/WebPanelUnitAdd",
      JSON.stringify(panelUnitData)
    );
    if (rs.data.isok && rs.data.response) {
      return rs.data.response;
    }
    throw new Error(rs.data.message || "创建面板单元失败");
  } catch (error) {
    console.error("创建面板单元失败:", error);
    throw error;
  }
};

/**
 * 查询Location数据
 */
const getLocationls = async (patternId) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/LocationQuery",
      JSON.stringify({ PID: patternId })
    );
    if (rs.data.isok && rs.data.response) {
      return JSON.parse(rs.data.response);
    }
    return [];
  } catch (error) {
    console.error("获取Location数据失败:", error);
    return [];
  }
};

/**
 * 获取所有图标库文件
 */
const getIconLibraries = async () => {
  try {
    const libraries = await fetchData("PanelSelection/IconLibraryQuery");
    iconLibraryList.value = libraries;
    // 并行加载所有图标库的图标
    const loadPromises = libraries.map(async (library) => {
      try {
        const icons = await fetchData("PanelSelection/IconQuery", {
          FID: library.ID,
        });
        iconOptions.value[library.ID] = icons;
      } catch (error) {
        console.error(`加载图标库 ${library.Series} 失败:`, error);
        iconOptions.value[library.ID] = [];
      }
    });

    await Promise.all(loadPromises);

    // 设置默认选中的图标库
    if (libraries.length > 0) {
      selectedIconLibrary.value = libraries[0].ID;
    }

    return libraries;
  } catch (error) {
    console.error("获取图标库列表失败:", error);
    iconLibraryList.value = [];
    return [];
  }
};

/**
 * 获取单个图标库的图标
 */
const getIconsByLibrary = async (libraryId) => {
  try {
    const icons = await fetchData("PanelSelection/IconQuery", {
      FID: libraryId,
    });
    iconOptions.value[libraryId] = icons;
    return icons;
  } catch (error) {
    console.error(`获取图标库 ${libraryId} 的图标失败:`, error);
    return [];
  }
};

/**
 * 图标选择变化处理
 */
const handleIconChange = (row) => {
  console.log("图标选择变化:", row);
};

/**
 * 检查面板单元是否存在
 */
const checkPanelUnitExists = async (panelUnitGuid) => {
  if (!panelUnitGuid) return false;

  try {
    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: panelUnitGuid }
    );
    const panelUnit = panelUnits[0];
    return !!panelUnit && panelUnit.is_valid;
  } catch (error) {
    console.error("检查面板单元存在性失败:", error);
    return false;
  }
};

/**
 * 加载已保存的面板单元配置
 */
const loadSavedPanelUnitConfig = async (panelUnitGuid) => {
  try {
    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: panelUnitGuid }
    );
    const panelUnit = panelUnits[0];
    if (panelUnit) {
      // 检查 elements_json 是否为空或无效
      if (
        !panelUnit.elements_json ||
        panelUnit.elements_json === "null" ||
        panelUnit.elements_json === "[]" ||
        panelUnit.elements_json === "{}"
      ) {
        // 使用默认数据构建合并数据
        buildMergedPanelUnitForm();
        return;
      }

      try {
        const savedConfig = JSON.parse(panelUnit.elements_json);

        if (
          savedConfig &&
          Array.isArray(savedConfig) &&
          savedConfig.length > 0
        ) {
          // 清空当前数据
          panelUnitForm.value = [];

          // 重新构建数据
          savedConfig.forEach((savedItem) => {
            // 根据保存的数据创建对应的表单项
            const formItem = {
              id: savedItem.locationId || Date.now() + Math.random(),
              locationId: savedItem.locationId || Date.now() + Math.random(),
              content: savedItem.content || "",
              size:
                savedItem.size ||
                (savedItem.type === 2 ? 11 : savedItem.type === 3 ? 7 : null),
              font: savedItem.font || "",
              locationName:
                savedItem.locationName ||
                `位置${savedItem.locationId || "未知"}`,
              type: savedItem.type || 1,
              backlightColor: savedItem.backlightColor || "#FFFFFF",
              backlightEnabled: savedItem.backlightEnabled || false,
              fileId: savedItem.fileId || null,
              iconId: savedItem.iconId || null,
              indexNum: savedItem.indexNum || 0,
              keygroup: savedItem.keygroup || 0,
              lineNumber: savedItem.lineNumber || 0,
            };

            panelUnitForm.value.push(formItem);
          });

          // 立即构建合并数据
          buildMergedPanelUnitForm();
        } else {
          buildMergedPanelUnitForm();
        }
      } catch (error) {
        console.error("解析保存的配置失败:", error);
        // 如果解析失败，使用默认数据
        buildMergedPanelUnitForm();
      }
    } else {
      buildMergedPanelUnitForm();
    }
  } catch (error) {
    console.error("加载保存的面板单元配置失败:", error);
    buildMergedPanelUnitForm();
  }
};

/**
 * 加载面板单元配置
 */
const loadPanelUnitConfiguration = async (panelUnitGuid, locations = null) => {
  try {
    const exists = await checkPanelUnitExists(panelUnitGuid);
    if (!exists) {
      ElMessage.warning("面板单元不存在");
      return;
    }

    currentPanelUnit.value = panelUnitGuid;

    // 获取面板单元详细信息
    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: panelUnitGuid }
    );
    const panelUnit = panelUnits[0];
    if (!panelUnit) {
      ElMessage.error("未找到面板单元信息");
      return;
    }

    const actualLocations = locations || [];
    // 初始化表单数据
    panelUnitForm.value = actualLocations
      .map((location, index) => {
        if (!location) {
          return null;
        }

        let defaultSize = null;
        let content = null;
        if (location.Type === 2) {
          defaultSize = 11;
          content = "空";
        } else if (location.Type === 3) {
          defaultSize = 7;
          content = "empty";
        }
        return {
          id: location.ID || Date.now() + index,
          locationId: location.ID || Date.now() + index,
          index: index + 1,
          content: content,
          size: defaultSize,
          font: "",
          locationName: location.LocationName || `位置${index + 1}`,
          type: location.Type || 1,
          sizeH: location.SizeH || 0,
          sizeW: location.SizeW || 0,
          backlightColor: "#FFFFFF",
          indexNum: location.IndexNum || 0,
          keygroup: location.Keygroup || 0,
          lineNumber: location.lineNumber || 0,
        };
      })
      .filter((item) => item !== null); // 过滤掉空项
    await loadSavedPanelUnitConfig(panelUnitGuid);
  } catch (error) {
    console.error("加载面板单元配置失败:", error);
    ElMessage.error("加载面板单元配置失败");
    // 即使失败也尝试构建默认数据
    buildMergedPanelUnitForm();
  }
};

/**
 * 更新单面板预览图
 */
const updateSinglePanelPreview = async (patternId) => {
  if (!patternId) {
    singlePanelPreview.value = "";
    return;
  }

  const pattern = patternsList.value.find((p) => p.ID === patternId);
  if (pattern && pattern.PreviewPath) {
    singlePanelPreview.value = config.PicAds + pattern.PreviewPath;
  } else {
    singlePanelPreview.value = "";
  }
};
/**
 * 手动刷新面板组预览图
 */
const refreshPanelGroupPreview = async () => {
  if (!currentPanelNode.value) {
    //ElMessage.warning('请先选择面板组');
    return;
  }

  try {
    showLoading("刷新面板组预览图中...");

    // 重新查询面板组数据
    const rs = await localHttp.post(
      "PanelSelection/WebPanelListQueryByGuid",
      JSON.stringify({ GUID: currentPanelNode.value.panelGuid })
    );

    if (rs.data.isok && rs.data.response) {
      const data = JSON.parse(rs.data.response);
      if (data.length > 0) {
        const panelInfo = data[0];

        // 更新当前面板组信息
        if (currentPanelNode.value) {
          currentPanelNode.value.panelInfo = panelInfo;
        }

        // 更新树节点中的面板组信息
        // updatePanelNodeInTree(currentPanelNode.value.panelGuid, panelInfo);

        if (
          panelInfo.thumbnail_large &&
          panelInfo.design_status !== "生成中"
        ) {
          panelGroupPreview.value = config.PicAds + panelInfo.thumbnail_large;
          await reloadTreeData();
          //ElMessage.success("面板组预览图刷新成功");
        } else {
          panelGroupPreview.value = "";
          //ElMessage.info('面板组预览图仍在生成中');
        }
      }
    }
  } catch (error) {
    console.error("刷新面板组预览失败:", error);
    ElMessage.error("刷新失败");
  } finally {
    hideLoading();
    // 移除 reloadTreeAndTriggerClick 调用，避免清空 mergedPanelUnitForm 数据
  }
};
/**
 * 手动刷新面板单元预览图
 */
const refreshPanelUnitPreview = async () => {
  if (!currentPanelUnit.value) {
    //ElMessage.warning('请先选择面板单元');
    return;
  }

  try {
    showLoading("刷新面板单元数据中...");
    singlePanelPreview.value = "";

    // 1. 保存当前选中的面板单元GUID
    const currentUnitGuid = currentPanelUnit.value;

    // 2. 重新加载左侧面板单元列表数据
    const projectNode = findProjectNode(selectedProjectId.value);
    if (projectNode?.webProject?.guid) {
      await loadPanelUnitsByProject(projectNode.webProject.guid);

      // 3. 在列表刷新完成后，自动重新选中用户当前正在查看的面板单元
      // 等待列表数据更新完成
      await nextTick();

      // 查找当前面板单元在刷新后的列表中的位置
      const refreshedUnit = unitTableData.value.find(
        (u) => u.guid === currentUnitGuid
      );
      if (refreshedUnit) {
        // 重新设置当前选中的面板单元
        currentPanelUnit.value = currentUnitGuid;
        await updateSinglePanelPreviewFromUnit(refreshedUnit);
      } else {
        // 如果刷新后找不到当前面板单元，清空选择
        currentPanelUnit.value = null;
        panelUnitForm.value = [];
        singlePanelPreview.value = "";
        ElMessage.warning("当前面板单元已不存在，已清空选择");
      }
    }
  } catch (error) {
    console.error("刷新面板单元数据失败:", error);
    ElMessage.error("刷新失败");
  } finally {
    hideLoading();
  }
};
/**
 * 保存面板单元配置
 */
const savePanelUnitConfig = async () => {
  if (!currentPanelUnit.value) {
    //ElMessage.warning('请先选择面板单元');
    return;
  }
  try {
    if (!mergedPanelUnitForm.value || mergedPanelUnitForm.value.length === 0) {
      hideLoading();
      ElMessage.warning("没有配置数据需要保存");
      return;
    }
    // 将合并数据转换回原始格式
    const flatData = [];

    mergedPanelUnitForm.value.forEach((locationGroup) => {
      if (!locationGroup) return;

      // 处理图标数据
      if (locationGroup.icon) {
        flatData.push({
          locationId: locationGroup.icon.locationId,
          content: locationGroup.icon.content,
          type: 1,
          size: locationGroup.icon.size || null,
          font: locationGroup.icon.font || "",
          locationName:
            locationGroup.icon.locationName || locationGroup.locationName,
          backlightColor: locationGroup.backlightColor || "#FFFFFF",
          backlightEnabled: locationGroup.backlightEnabled || false,
          fileId: locationGroup.icon.fileId || null,
          iconId: locationGroup.icon.iconId || null,
          indexNum: locationGroup.icon.indexNum || 0,
          keygroup: locationGroup.icon.keygroup || 0,
          lineNumber: locationGroup.icon.lineNumber || 0,
        });
      }

      // 处理中文数据
      if (locationGroup.chinese) {
        flatData.push({
          locationId: locationGroup.chinese.locationId,
          content: locationGroup.chinese.content || "",
          type: 2,
          size: locationGroup.chinese.size || 11,
          font: locationGroup.chinese.font || "",
          locationName:
            locationGroup.chinese.locationName || locationGroup.locationName,
          backlightColor: locationGroup.backlightColor || "#FFFFFF",
          backlightEnabled: locationGroup.backlightEnabled || false,
          indexNum: locationGroup.chinese.indexNum || 0,
          keygroup: locationGroup.chinese.keygroup || 0,
          lineNumber: locationGroup.chinese.lineNumber || 0,
        });
      }

      // 处理英文数据
      if (locationGroup.english) {
        flatData.push({
          locationId: locationGroup.english.locationId,
          content: locationGroup.english.content || "",
          type: 3,
          size: locationGroup.english.size || 7,
          font: locationGroup.english.font || "",
          locationName:
            locationGroup.english.locationName || locationGroup.locationName,
          backlightColor: locationGroup.backlightColor || "#FFFFFF",
          backlightEnabled: locationGroup.backlightEnabled || false,
          indexNum: locationGroup.english.indexNum || 0,
          keygroup: locationGroup.english.keygroup || 0,
          lineNumber: locationGroup.english.lineNumber || 0,
        });
      }
    });

    // 如果没有任何数据，保存空数组
    const elementsToSave = flatData.length > 0 ? flatData : [];

    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: currentPanelUnit.value }
    );
    const panelUnit = panelUnits[0];

    if (panelUnit) {
      let projectGuid = "";
      if (selectedProjectId.value) {
        const projectNode = findProjectNode(selectedProjectId.value);
        if (projectNode && projectNode.webProject) {
          projectGuid = projectNode.webProject.guid;
        }
      }

      if (!projectGuid && panelUnit.project_guid) {
        projectGuid = panelUnit.project_guid;
      }

      const updateData = {
        ...panelUnit,
        elements_json: JSON.stringify(elementsToSave),
        project_guid: projectGuid,
        element_count: elementsToSave.length,
        // 清空预览相关字段
        thumbnail_large: "",
        cdr_filename: "",
      };
      await updateDatabase("PanelSelection/WebPanelUnitUpdate", updateData);
        // 调用GetProjectStatus更新项目状态
        await GetProjectStatus();

      // 保存成功后刷新面板单元列表
      if (projectGuid) {
        await loadPanelUnitsByProject(projectGuid);
      }

      // 清空当前预览图
      singlePanelPreview.value = "";

      //ElMessage.success("配置保存成功");

      // 保存成功后重载树数据并重新选中当前节点
      await reloadTreeData();
    } else {
      ElMessage.error("未找到对应的面板单元");
    }
  } catch (error) {
    console.error("保存面板单元配置失败:", error);
    ElMessage.error("保存面板单元配置失败");
  }
};

/**
 * 面板单元行点击事件
 */
const handleUnitRowClick = async (row) => {
  try {
    showLoading("加载面板单元配置中...");
    isUserEditingPanelUnit.value = false;
    // 设置当前选中的面板单元
    currentPanelUnit.value = row.guid;

    // 先尝试获取该面板单元对应的位置信息
    let locations = [];
    if (row.series_id && row.pattern_id) {
      // 使用存储的系列和面板ID获取位置信息
      const series = seriesList.value.find((s) => s.ID === row.series_id);
      if (series) {
        const patterns = await fetchData("PanelSelection/PatternQuery", {
          FID: series.ID,
        });
        const pattern = patterns.find((p) => p.ID === row.pattern_id);

        if (pattern) {
          locations = await getLocationls(pattern.ID);
        }
      }
    }

    // 加载面板单元配置到右侧表单
    await loadPanelUnitConfiguration(row.guid, locations);

    // 更新单面板预览图
    await updateSinglePanelPreviewFromUnit(row);

    hideLoading();
    //ElMessage.success(`已加载面板单元: ${row.panel_name}`);
  } catch (error) {
    hideLoading();
    console.error("加载面板单元配置失败:", error);
    ElMessage.error("加载面板单元配置失败");
  }
};

/**
 * 处理图标库行点击
 */
const handleIconLibraryRowClick = (row) => {
  selectedIconLibrary.value = row.ID;
};
/**
 * 清除当前编辑状态
 */
const clearEditingStatus = () => {
  currentPanelUnit.value = null;
  // 清除面板配置表格的编辑状态
  panelConfigTable.value.forEach((item) => {
    item.isEditing = false;
  });
};
/**
 * 系列选择变化处理（面板单元）
 */
const handleSeriesChangeForUnit = async (currentRow) => {
  selectedSeriesForUnit.value = currentRow;

  if (currentRow) {

    // 注意：这里不需要手动调用getModelsForUnit和getPatternsForUnit
    // 因为watch监听器会自动处理
  } else {
    selectedDirectionForUnit.value = "";
    selectedColorForUnit.value = "";
    selectedPatternForUnit.value = "";
  }
};

/**
 * 获取模型数据（面板单元）
 */
const getModelsForUnit = async (fileId) => {
  try {
    const rs = await localHttp.post(
      "PanelSelection/ModelQuery",
      JSON.stringify({ FID: fileId })
    );
    if (rs.data.isok && rs.data.response) {
      const allModelsData = JSON.parse(rs.data.response);
      allModelsForUnit.value = allModelsData;

      // 过滤出面板数为1的模型
      const singlePanelModels = allModelsData.filter(
        (model) => model.PanelCount === 1
      );

      // 确保选项是有效的字符串数组
      directionOptionsForUnit.value = [
        ...new Set(
          singlePanelModels
            .map((model) => model.Direction)
            .filter((dir) => dir && dir.trim() !== "")
        ),
      ];

      colorOptionsForUnit.value = [
        ...new Set(
          singlePanelModels
            .map((model) => model.Color)
            .filter((color) => color && color.trim() !== "")
        ),
      ];

      // 保存所有模型供后续使用
      filteredModelsForUnit.value = singlePanelModels;

      // 自动触发模型更新
      updateModelListForUnit();

      return singlePanelModels;
    } else {
      filteredModelsForUnit.value = [];
      directionOptionsForUnit.value = [];
      colorOptionsForUnit.value = [];
      return [];
    }
  } catch (error) {
    console.error("获取模型列表失败:", error);
    filteredModelsForUnit.value = [];
    directionOptionsForUnit.value = [];
    colorOptionsForUnit.value = [];
    return [];
  }
};

/**
 * 获取Pattern列表（面板单元）
 */
const getPatternsForUnit = async (fileId) => {
  try {
    const patterns = await fetchData("PanelSelection/PatternQuery", {
      FID: fileId,
    });
    // 过滤有效的面板数据
    patternsListForUnit.value = patterns.filter(
      (p) => p && p.PatternName && p.PatternName.trim() !== ""
    );
    return patterns;
  } catch (error) {
    console.error("获取Pattern列表失败:", error);
    patternsListForUnit.value = [];
    return [];
  }
};

/**
 * 更新模型列表（面板单元）
 */
const updateModelListForUnit = async () => {
  if (!selectedSeriesForUnit.value) return;

  // 过滤出面板数为1的模型
  const singlePanelModels = allModelsForUnit.value.filter(
    (model) => model.PanelCount === 1
  );

  // 如果有方向或颜色选择，进一步过滤
  let filteredModels = singlePanelModels;

  if (selectedDirectionForUnit.value) {
    filteredModels = filteredModels.filter(
      (model) => model.Direction === selectedDirectionForUnit.value
    );
  }

  if (selectedColorForUnit.value) {
    filteredModels = filteredModels.filter(
      (model) => model.Color === selectedColorForUnit.value
    );
  }
  // 自动选择第一个匹配的模型
  if (filteredModels.length > 0) {
    selectedModelForUnit.value = filteredModels[0];
    if (selectedPatternForUnit.value) {
      await getPatternsForUnit(selectedSeriesForUnit.value.ID);
      const selectedPattern = patternsListForUnit.value.find(
        (p) => p.ID === selectedPatternForUnit.value
      );
      selectedSeriesPreviewForUnit.value = config.PicAds + selectedPattern.PreviewPath;
    }

  } else {
    selectedModelForUnit.value = null;
    // 如果没有匹配的，选择面板数为1的第一个模型
    if (singlePanelModels.length > 0) {
      selectedModelForUnit.value = singlePanelModels[0];
      // 更新选择器的值为自动选择的模型值
      selectedDirectionForUnit.value = singlePanelModels[0].Direction;
      selectedColorForUnit.value = singlePanelModels[0].Color;
    }
  }
};

// 显示添加面板单元对话框
const showAddPanelUnitDialogView = () => {
  resetPanelUnitDialog();
  showAddPanelUnitDialog.value = true;
};
/**
 * 重置面板单元对话框
 */
const resetPanelUnitDialog = () => {
  selectedSeriesForUnit.value = null;
  selectedDirectionForUnit.value = "";
  selectedColorForUnit.value = "";
  selectedPatternForUnit.value = "";
  patternsListForUnit.value = [];
  filteredModelsForUnit.value = [];
  directionOptionsForUnit.value = [];
  colorOptionsForUnit.value = [];
  newPanelUnitForm.value = {
    panel_name: "",
    remarks: "",
  };
  // 重置编辑状态
  isEditPanelUnit.value = false;
  currentEditPanelUnit.value = null;
};

/**
 * 确认添加面板单元
 */
const confirmAddPanelUnit = async () => {
  if (!newPanelUnitForm.value.panel_name) {
    ElMessage.error("请填写面板单元名称");
    return;
  }

  if (!selectedSeriesForUnit.value) {
    ElMessage.error("请选择系列");
    return;
  }

  if (!selectedPatternForUnit.value) {
    ElMessage.error("请选择面板");
    return;
  }

  try {
    // 从项目选择器中获取项目GUID
    let projectGuid = "";
    if (selectedProjectId.value) {
      const projectNode = findProjectNode(selectedProjectId.value);
      if (projectNode && projectNode.webProject) {
        projectGuid = projectNode.webProject.guid;
      }
    }

    if (!projectGuid) {
      ElMessage.error("未找到当前项目信息，请先选择项目");
      return;
    }

    // 获取选中的Pattern信息
    const selectedPattern = patternsListForUnit.value.find(
      (p) => p.ID === selectedPatternForUnit.value
    );
    if (!selectedPattern) {
      ElMessage.error("未找到选中的面板信息");
      return;
    }

    // 准备保存的数据 - 直接使用字段存储
    const panelUnitData = {
      panel_name: newPanelUnitForm.value.panel_name,
      product_type: selectedPattern.PatternName,
      element_count: 0,
      elements_json: "[]",
      cdr_filename: "",
      thumbnail_large: "",
      thumbnail_small: "",
      remarks: newPanelUnitForm.value.remarks || "",
      erp_part_number: "",
      design_status: "",
      owner: getCurrentUser(),
      share_type: "私有",
      project_guid: projectGuid,
      // 直接存储选择信息到字段
      series_id: selectedSeriesForUnit.value.ID,
      pattern_id: selectedPatternForUnit.value,
      direction: selectedDirectionForUnit.value || "",
      color: selectedColorForUnit.value || "",
      model_type: selectedModelForUnit.value?.ModelName || "",
      model_id: selectedModelForUnit.value?.ID || null,
    };

    // 调用API保存面板单元
    const newGuid = await createPanelUnit(panelUnitData);

    if (newGuid) {
      ElMessage.success("面板单元添加成功");
      showAddPanelUnitDialog.value = false;

      // 刷新面板单元列表
      await loadPanelUnitsByProject(projectGuid);

      // 重置对话框
      resetPanelUnitDialog();
    } else {
      ElMessage.error("面板单元添加失败");
    }
  } catch (error) {
    console.error("添加面板单元失败:", error);
    ElMessage.error("添加面板单元失败: " + error.message);
  }
};

/**
 * 更新面板单元
 */
const updatePanelUnit = async () => {
  if (!newPanelUnitForm.value.panel_name) {
    ElMessage.error("请填写面板单元名称");
    return;
  }

  if (!currentEditPanelUnit.value) {
    ElMessage.error("未找到要编辑的面板单元");
    return;
  }

  if (!selectedSeriesForUnit.value) {
    ElMessage.error("请选择系列");
    return;
  }

  if (!selectedPatternForUnit.value) {
    ElMessage.error("请选择面板");
    return;
  }

  try {
    let projectGuid = "";
    if (selectedProjectId.value) {
      const projectNode = findProjectNode(selectedProjectId.value);
      if (projectNode && projectNode.webProject) {
        projectGuid = projectNode.webProject.guid;
      }
    }

    if (!projectGuid && currentEditPanelUnit.value.project_guid) {
      projectGuid = currentEditPanelUnit.value.project_guid;
    }

    const selectedPattern = patternsListForUnit.value.find(
      (p) => p.ID === selectedPatternForUnit.value
    );
    if (!selectedPattern) {
      ElMessage.error("未找到选中的面板信息");
      return;
    }

    // 更新时清空预览相关字段
    const updateData = {
      ...currentEditPanelUnit.value,
      panel_name: newPanelUnitForm.value.panel_name,
      product_type: selectedPattern.PatternName,
      remarks: newPanelUnitForm.value.remarks || "",
      series_id: selectedSeriesForUnit.value.ID,
      pattern_id: selectedPatternForUnit.value,
      direction: selectedDirectionForUnit.value || "",
      color: selectedColorForUnit.value || "",
      project_guid: projectGuid,
      // 清空预览相关字段
      elements_json: "[]",
      thumbnail_large: "",
      cdr_filename: "",
    };
    await updateDatabase("PanelSelection/WebPanelUnitUpdate", updateData);

    //ElMessage.success("面板单元更新成功，预览图已重置");
    showAddPanelUnitDialog.value = false;

    // 刷新列表
    if (projectGuid) {
      await loadPanelUnitsByProject(projectGuid);
    }

    // 重置状态
    resetPanelUnitDialog();
  } catch (error) {
    console.error("更新面板单元失败:", error);
    ElMessage.error("更新面板单元失败: " + error.message);
  }
};

/**
 * 在系列加载完成后恢复选择
 */
const restoreSelectionsAfterSeriesLoad = async () => {
  if (!currentEditPanelUnit.value) return;

  const panelUnit = currentEditPanelUnit.value;

  // 确保数据已经加载完成
  await new Promise((resolve) => setTimeout(resolve, 100));

  // 恢复方向选择
  if (panelUnit.direction) {
    if (directionOptionsForUnit.value.includes(panelUnit.direction)) {
      selectedDirectionForUnit.value = panelUnit.direction;
    }
  }

  // 恢复颜色选择
  if (panelUnit.color) {
    if (colorOptionsForUnit.value.includes(panelUnit.color)) {
      selectedColorForUnit.value = panelUnit.color;
    }
  }

  // 恢复面板选择
  if (panelUnit.pattern_id) {
    const pattern = patternsListForUnit.value.find(
      (p) => p.ID === panelUnit.pattern_id
    );
    selectedSeriesPreviewForUnit.value = config.PicAds + pattern.PreviewPath;
    if (pattern) {
      selectedPatternForUnit.value = panelUnit.pattern_id;
    }
  }
};
/**
 * 获取图标库名称
 */
const getLibraryName = (libraryId) => {
  const library = iconLibraryList.value.find((lib) => lib.ID === libraryId);
  return library ? `${library.Series}_${library.Version}` : "未知库";
};

/**
 * 打开图标选择对话框
 */
const openIconDialog = (location) => {
  currentEditingLocation.value = location;
  currentEditingType.value = "icon";

  // 自动选择
  selectedIconLibrary.value = iconLibraryList.value[0].ID;

  iconDialogVisible.value = true;
};

/**
 * 打开中文编辑对话框
 */
const openChineseDialog = (location) => {
  currentEditingLocation.value = location;
  currentEditingType.value = "chinese";

  // 初始化表单数据
  if (!location.chinese) {
    location.chinese = {
      content: "",
      font: "",
      size: 11, // 中文默认字号
    };
  }
  chineseDialogVisible.value = true;
};

/**
 * 打开英文编辑对话框
 */
const openEnglishDialog = (location) => {
  currentEditingLocation.value = location;
  currentEditingType.value = "english";

  // 初始化表单数据
  if (!location.english) {
    location.english = {
      content: "",
      font: "",
      size: 7, // 英文默认字号
    };
  }
  englishDialogVisible.value = true;
};
/**
 * 保存图标配置
 */
const saveIconConfig = (iconData) => {
  if (currentEditingLocation.value) {
    // 确保图标对象存在
    if (!currentEditingLocation.value.icon) {
      currentEditingLocation.value.icon = {
        id: currentEditingLocation.value.icon.id || Date.now(),
        locationId:
          currentEditingLocation.value.locations?.[0]?.locationId || Date.now(),
        content: "",
        type: 1,
        locationName:
          currentEditingLocation.value.icon.locationName ||
          currentEditingLocation.value.locationName,
        indexNum: currentEditingLocation.value.icon.indexNum || 0,
        keygroup: currentEditingLocation.value.icon.keygroup || 0,
        lineNumber: currentEditingLocation.value.icon.lineNumber || 0,
      };
    }
    // 更新图标配置
    currentEditingLocation.value.icon = {
      ...currentEditingLocation.value.icon,
      content: iconData.ShapeNumber,
      type: 1,
      iconId: iconData.ID,
      fileId: iconData.FID,
      libraryName: getLibraryName(iconData.FID),
      locationName:
        currentEditingLocation.value.icon.locationName ||
        currentEditingLocation.value.locationName,
      indexNum: currentEditingLocation.value.icon.indexNum || 0,
      keygroup: currentEditingLocation.value.icon.keygroup || 0,
      lineNumber: currentEditingLocation.value.icon.lineNumber || 0,
    };

    // 新增：自动设置中文和英文内容
    // 确保中文对象存在
    if (!currentEditingLocation.value.chinese) {
      currentEditingLocation.value.chinese = {
        id: currentEditingLocation.value.chinese.id || Date.now() + 1, // 确保ID不同
        locationId:
          currentEditingLocation.value.chinese.locationId || Date.now() + 1,
        content: "",
        type: 2,
        font: "", // TODO 默认字体
        size: 11, // 中文默认字号
        locationName:
          currentEditingLocation.value.chinese.locationName ||
          currentEditingLocation.value.locationName,
        indexNum: currentEditingLocation.value.chinese.indexNum || 0,
        keygroup: currentEditingLocation.value.chinese.keygroup || 0,
        lineNumber: currentEditingLocation.value.chinese.lineNumber || 0,
      };
    }

    // 确保英文对象存在
    if (!currentEditingLocation.value.english) {
      currentEditingLocation.value.english = {
        id: currentEditingLocation.value.english.id || Date.now() + 2, // 确保ID不同
        locationId:
          currentEditingLocation.value.english.locationId || Date.now() + 2,
        content: "",
        type: 3,
        font: "",
        size: 7, // 英文默认字号
        locationName:
          currentEditingLocation.value.english.locationName ||
          currentEditingLocation.value.locationName,
        indexNum: currentEditingLocation.value.english.indexNum || 0,
        keygroup: currentEditingLocation.value.english.keygroup || 0,
        lineNumber: currentEditingLocation.value.english.lineNumber || 0,
      };
    }

    // 使用图标数据的中英文名称自动填充内容
    if (iconData.NameCN) {
      currentEditingLocation.value.chinese.content = iconData.NameCN || "空";
      // 设置默认中文字体（如果当前没有设置）
      if (
        !currentEditingLocation.value.chinese.font &&
        fontList.value.length > 0
      ) {
        currentEditingLocation.value.chinese.font = "思源黑体";
      }
    }

    if (iconData.NameEn) {
      currentEditingLocation.value.english.content = iconData.NameEn || "empty";
      // 设置默认英文字体（如果当前没有设置）
      if (
        !currentEditingLocation.value.english.font &&
        fontList.value.length > 0
      ) {
        currentEditingLocation.value.english.font = "Futura Std Medium";
      }
    }

    // 同步背光设置到中文和英文对象
    if (currentEditingLocation.value.backlightEnabled) {
      currentEditingLocation.value.chinese.backlightColor =
        currentEditingLocation.value.backlightColor;
      currentEditingLocation.value.chinese.backlightEnabled =
        currentEditingLocation.value.backlightEnabled;
      currentEditingLocation.value.english.backlightColor =
        currentEditingLocation.value.backlightColor;
      currentEditingLocation.value.english.backlightEnabled =
        currentEditingLocation.value.backlightEnabled;
    }

    updatePanelUnitFormFromMerged();
    savePanelUnitConfig();
    iconDialogVisible.value = false;
    //ElMessage.success("图标选择成功，已自动填充中英文内容");
  }
};
/**
 * 从合并数据更新 panelUnitForm
 */
const updatePanelUnitFormFromMerged = () => {
  // 清空现有数据
  panelUnitForm.value = [];

  // 从合并数据重建 panelUnitForm
  mergedPanelUnitForm.value.forEach((location) => {
    if (location.icon) {
      panelUnitForm.value.push({
        ...location.icon,
        locationName: location.originalLocationName || location.locationName,
      });
    }
    if (location.chinese) {
      panelUnitForm.value.push({
        ...location.chinese,
        locationName: location.originalLocationName || location.locationName,
      });
    }
    if (location.english) {
      panelUnitForm.value.push({
        ...location.english,
        locationName: location.originalLocationName || location.locationName,
      });
    }
  });
};
/**
 * 保存中文配置
 */
const saveChineseConfig = () => {
  if (currentEditingLocation.value) {
    // 确保中文对象存在
    if (!currentEditingLocation.value.chinese) {
      currentEditingLocation.value.chinese = {
        id: currentEditingLocation.value.locations?.[0]?.id || Date.now(),
        locationId:
          currentEditingLocation.value.locations?.[0]?.locationId || Date.now(),
        content: "",
        type: 2,
        locationName:
          currentEditingLocation.value.originalLocationName ||
          currentEditingLocation.value.locationName,
      };
    }

    const currentFont = currentEditingLocation.value.chinese.font;
    const currentSize = currentEditingLocation.value.chinese.size;

    // 统一设置所有为空的中文字体和字号
    if (currentFont || currentSize) {
      mergedPanelUnitForm.value.forEach((row) => {
        if (!row.chinese) {
          row.chinese = {
            content: "",
            font: "",
            size: 11,
          };
        }

        // 如果当前行中文字体为空，且编辑的字体不为空，则统一设置
        if (currentFont && !row.chinese.font) {
          row.chinese.font = currentFont;
        }

        // 如果当前行中文字号为空，且编辑的字号不为空，则统一设置
        if (currentSize && !row.chinese.size) {
          row.chinese.size = currentSize;
        }
      });
    }

    chineseDialogVisible.value = false;
    updatePanelUnitFormFromMerged();
    savePanelUnitConfig();
  }
};

/**
 * 保存英文配置
 */
const saveEnglishConfig = () => {
  if (currentEditingLocation.value) {
    // 确保英文对象存在
    if (!currentEditingLocation.value.english) {
      currentEditingLocation.value.english = {
        id: currentEditingLocation.value.locations?.[0]?.id || Date.now(),
        locationId:
          currentEditingLocation.value.locations?.[0]?.locationId || Date.now(),
        content: "",
        type: 3,
        locationName:
          currentEditingLocation.value.originalLocationName ||
          currentEditingLocation.value.locationName,
      };
    }

    const currentFont = currentEditingLocation.value.english.font;
    const currentSize = currentEditingLocation.value.english.size;

    // 统一设置所有为空的英文字体和字号
    if (currentFont || currentSize) {
      mergedPanelUnitForm.value.forEach((row) => {
        if (!row.english) {
          row.english = {
            content: "",
            font: "",
            size: 7,
          };
        }

        // 如果当前行英文字体为空，且编辑的字体不为空，则统一设置
        if (currentFont && !row.english.font) {
          row.english.font = currentFont;
        }

        // 如果当前行英文字号为空，且编辑的字号不为空，则统一设置
        if (currentSize && !row.english.size) {
          row.english.size = currentSize;
        }
      });
    }

    englishDialogVisible.value = false;
    updatePanelUnitFormFromMerged();
    savePanelUnitConfig();
  }
};
/**
 * 根据FID获取文件名
 */
const getFileNameByFid = (fid) => {
  if (!fid) return "";
  const series = seriesList.value.find((s) => s.ID === fid);
  return series ? series.FileName : "";
};
/**
 * 获取图标预览URL
 */
const getIconPreviewUrl = (iconData) => {
  if (!iconData || !iconData.fileId || !iconData.content) {
    return "";
  }

  try {
    // 查找对应的图标库
    const library = iconLibraryList.value.find(
      (lib) => lib.ID === iconData.fileId
    );
    if (!library) return "";

    // 查找具体的图标数据
    const icons = iconOptions.value[iconData.fileId] || [];
    const icon = icons.find((i) => i.ShapeNumber === iconData.content);

    if (icon && icon.PreviewPath) {
      return config.PicAds + icon.PreviewPath;
    }

    return "";
  } catch (error) {
    console.error("获取图标预览URL失败:", error);
    return "";
  }
};
/**
 * 根据图标ID获取对应的文件名
 */
const getIconFileName = async (iconId, defaultFid = null) => {
  if (!iconId) return "";

  try {
    // 首先尝试从所有图标库中查找该图标
    for (const libraryId in iconOptions.value) {
      const icons = iconOptions.value[libraryId];
      const icon = icons.find((i) => i.ID === iconId);
      if (icon) {
        return getFileNameByFid(icon.FID);
      }
    }

    // 如果找不到，使用默认的FID
    if (defaultFid) {
      return getFileNameByFid(defaultFid);
    }

    return "";
  } catch (error) {
    console.error("获取图标文件名失败:", error);
    return "";
  }
};
/**
 * 自动保存单个面板配置到remark字段
 */
const autoSavePanelUnitConfig = async () => {
  if (!currentPanelUnit.value) return;

  try {
    // 生成previewObject结构体
    const previewObject = await generateSinglePanelPreviewObject(false); // false表示不生成图

    if (!previewObject) {
      console.warn("生成单个面板预览对象失败");
      return;
    }

    // 获取当前面板单元信息
    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: currentPanelUnit.value }
    );
    const panelUnit = panelUnits[0];
    if (panelUnit) {
      // 准备保存的数据
      const saveData = {
        ...panelUnit,
        remarks: JSON.stringify({
          previewObject: previewObject,
          savedAt: new Date().toISOString(),
          version: "1.0",
        }),
      };
      // 保存到数据库
      await updateDatabase("PanelSelection/WebPanelUnitUpdate", saveData);
      // 调用GetProjectStatus更新项目状态
      await GetProjectStatus();
    }
  } catch (error) {
    console.error("自动保存单个面板配置失败:", error);
  }
};

/**
 * 自动保存面板组配置到remark字段
 */
const autoSavePanelGroupConfig = async () => {
  if (!currentPanelNode.value) return;

  try {
    // 生成结构化数据
    const structureData = await generatePanelGroupStructureData(false); // false表示不生成图

    if (!structureData) {
      console.warn("生成面板组结构化数据失败");
      return;
    }

    // 获取当前面板组信息
    const panelInfo = await getPanelInfoByGuid(
      currentPanelNode.value.panelGuid
    );
    if (panelInfo) {
      // 准备保存的数据
      const saveData = {
        ...panelInfo,
        remarks: JSON.stringify({
          structureData: structureData,
          savedAt: new Date().toISOString(),
          version: "1.0",
        }),
      };

      // 保存到数据库
      await updateDatabase("PanelSelection/WebPanelListUpdate", saveData);
      // 调用GetProjectStatus更新项目状态
      await GetProjectStatus();
    }
  } catch (error) {
    console.error("自动保存面板组配置失败:", error);
  }
};

/**
 * 清空面板组预览图（任务3）
 */
const clearPanelGroupPreview = async () => {
  if (!currentPanelNode.value) return;

  try {
    // 清空本地变量
    panelGroupPreview.value = "";

    // 清空数据库中的预览图字段
    const panelInfo = await getPanelInfoByGuid(
      currentPanelNode.value.panelGuid
    );
    if (panelInfo) {
      const updateData = {
        ...panelInfo,
        thumbnail_large: "", // 清空大缩略图
      };

      await updateDatabase("PanelSelection/WebPanelListUpdate", updateData);
    }
  } catch (error) {
    console.error("清空面板组预览图失败:", error);
  }
};

/**
 * 生成单个面板预览对象（重构自showSinglePanelPreview）
 */
const generateSinglePanelPreviewObject = async (generateImage = true) => {
  if (!currentPanelUnit.value) return null;
  try {
    const currentUser = getCurrentUser();
    const projectNode = findProjectNode(selectedProjectId.value);

    if (!projectNode || !projectNode.webProject) {
      return null;
    }
    const hotel_name = projectNode.webProject.hotel_name;
    const projectId = projectNode.webProject.report_id;
    const timestamp = Date.now().toString();
    const pictureNumSuffix = timestamp.slice(-8);


    // 获取当前面板单元信息
    const panelUnits = await fetchData(
      "PanelSelection/WebPanelUnitQueryByGuid",
      { GUID: currentPanelUnit.value }
    );
    const panelUnit = panelUnits[0];
    if (!panelUnit) return null;
    const pictureNum = `Unit_${hotel_name}_${panelUnit.panel_name}_${pictureNumSuffix}`;
    let materialLibraryName = "";
    let templateName = "";
    let templateNameIndex = "";
    let matchedModel = null;

    // 获取系列信息
    if (panelUnit.series_id) {
      const series = seriesList.value.find((s) => s.ID === panelUnit.series_id);
      if (series) {
        materialLibraryName = series.FileName;

        // 参考面板组合的模板名称赋值逻辑
        if (panelUnit.model_type) {
          // 如果面板单元保存了模型类型，直接使用
          templateName = panelUnit.model_type;
        } else {
          // 否则使用系列名称作为备用
          templateName = series.Series;
        }
      }
    }

    // 获取模型信息来设置 templateNameIndex
    if (panelUnit.series_id) {
      const models = await fetchData("PanelSelection/ModelQuery", {
        FID: panelUnit.series_id,
      });

      // 优先使用面板单元保存的模型信息
      if (panelUnit.model_id) {
        matchedModel = models.find((model) => model.ID === panelUnit.model_id);
      }

      // 如果没有保存的模型ID，尝试通过其他条件匹配
      if (!matchedModel && panelUnit.model_type) {
        matchedModel = models.find(
          (model) => model.ModelName === panelUnit.model_type
        );
      }

      // 如果还没有匹配，查找面板数为1的模型
      if (!matchedModel) {
        matchedModel = models.find((model) => model.PanelCount === 1);
      }

      // 如果仍然没有匹配，选择面板数最小的模型
      if (!matchedModel && models.length > 0) {
        matchedModel = models.reduce((minModel, currentModel) => {
          return currentModel.PanelCount < (minModel?.PanelCount || Infinity)
            ? currentModel
            : minModel;
        });
      }

      if (matchedModel) {
        templateNameIndex = matchedModel.ShapeNumber;
        // 确保templateName使用模型的名称
        if (!panelUnit.model_type) {
          templateName = matchedModel.ModelName;
        }
      }
    }

    // 获取Pattern信息
    let patternFileName = "";
    let patternShapeNumber = "";

    if (panelUnit.pattern_id) {
      const patterns = await fetchData("PanelSelection/PatternQuery", {
        FID: panelUnit.series_id,
      });
      const pattern = patterns.find((p) => p.ID === panelUnit.pattern_id);
      if (pattern) {
        patternShapeNumber = pattern.ShapeNumber || "";

        // 获取Pattern对应的文件名
        if (pattern.FID) {
          const patternSeries = seriesList.value.find(
            (s) => s.ID === pattern.FID
          );
          patternFileName = patternSeries ? patternSeries.FileName : "";
        }
      }
    }

    const locationList = [];

    // 处理元素数据
    if (panelUnit.elements_json) {
      try {
        const elementsData = JSON.parse(panelUnit.elements_json);
        const locations = await getLocationls(panelUnit.pattern_id);

        for (let j = 0; j < elementsData.length; j++) {
          const element = elementsData[j];
          const location = locations.find(
            (loc) => loc.ID === element.locationId
          );

          let shapeNumber = "";
          let fileName = "";
          let shapeType = 0;
          let shapeColor = element.backlightColor || "#FFFFFF";
          let shapeFont = element.font || "";
          let shapeFontSize = parseFloat(element.size) || 0.0;
          let lineNumber = "";

          if (element.content) {
            if (element.type === 1) {
              // 图标类型
              shapeType = 1;
              const fileId = element.fileId || panelUnit.series_id;
              if (fileId) {
                const icons = await fetchData("PanelSelection/IconQuery", {
                  FID: fileId,
                });

                const icon = icons.find(
                  (icon) => icon.ShapeNumber === element.content
                );

                shapeNumber =
                  icon && icon.ShapeNumber != null
                    ? String(icon.ShapeNumber)
                    : String(element.content);

                // 获取图标对应的文件名
                if (icon && icon.FID) {
                  const iconSeries = seriesList.value.find(
                    (s) => s.ID === icon.FID
                  );
                  fileName = iconSeries ? iconSeries.FileName : "";
                }
              } else {
                shapeNumber = String(element.content);
              }
            } else {
              // 文字类型
              shapeType = 0;
              shapeNumber = String(element.content);
              shapeFont = element.font || "";
              shapeFontSize = parseFloat(element.size) || 0.0;

              // 解析行号
              if (location && location.lineNumber) {
                lineNumber = location.lineNumber.toString();
              }
            }
          }

          let remark = "";
          if (element.type !== 1 && (element.font || element.size)) {
            remark = `${element.font || ""}_${element.size || ""}`;
            if (lineNumber) {
              remark += `_${lineNumber}`;
            }
          }

          locationList.push({
            IndexNumber: element.indexNum.toString(),
            Remark: remark,
            ShapeNumber: shapeNumber,
            ShapeType: shapeType,
            FileName: fileName,
            ShapeColor: shapeColor,
            ShapeFont: shapeFont,
            ShapeFontSize: shapeFontSize,
            LineNumber:
              element.lineNumber.toString() !== "0"
                ? element.lineNumber.toString()
                : "",
          });
        }
      } catch (error) {
        console.error("解析面板单元数据失败:", error);
      }
    }

    // 获取Trench数据
    const Trench = await fetchData("PanelSelection/TrenchQuery", {
      MID: matchedModel ? matchedModel.ID : 0,
    });

    const pindxn = Trench.find((item) => item.TrenchName.split("_")[1] === "1");

    const patternList = [
      {
        IndexNumber: pindxn ? pindxn.IndexNum.toString() : "1",
        ShapeNumber: patternShapeNumber,
        FileName: patternFileName,
        LocationList: locationList,
      },
    ];

    // 构建完整的previewObject结构体
    const previewObject = {
      Guid: panelUnit.guid,
      MaterialLibraryName: materialLibraryName || "未找到图库文件",
      PictureNum: pictureNum,
      Process: generateImage ? 0 : -1, // -1表示只生成结构体
      ProjectId: projectId || "未知项目ID",
      ProjectName: hotel_name || "未知酒店",
      TemplateName: templateName || "未找到模板",
      TemplateNameIndex: templateNameIndex || "未找到模板索引",
      User: currentUser || "未知用户",
      LogoPosition: "",
      LogoFileName: "",
      LogoIndexNumber: "",
      PatternList: patternList,
    };

    return previewObject;
  } catch (error) {
    console.error("生成单个面板预览对象失败:", error);
    return null;
  }
};

/**
 * 生成面板组结构化数据（重构自showPreview）
 */
const generatePanelGroupStructureData = async (generateImage = true) => {
  if (!currentPanelNode.value) return null;

  try {
    // 设置标记，防止watch监听器触发，避免无限循环
    isGeneratingStructureData.value = true;

    // 1. 重新获取面板组信息
    const latestPanelInfo = await getPanelInfoByGuid(
      currentPanelNode.value.panelGuid
    );
    if (latestPanelInfo) {
      currentPanelNode.value.panelInfo = latestPanelInfo;
    }

    // 2. 重新获取面板单元数据
    /*      const latestPanelUnits = await fetchData('PanelSelection/WebPanelUnitQuery');
          // 更新unitTableData，availablePanelUnits会自动计算
          unitTableData.value = latestPanelUnits;*/

    // 3. 重新初始化面板配置表格，确保数据是最新的
    initPanelConfigTable(currentPanelNode.value);

    const currentUser = getCurrentUser();
    const projectNode = findProjectNode(currentPanelNode.value.projectId);

    if (!projectNode || !projectNode.webProject) {
      return null;
    }

    const hotel_name = projectNode.webProject.hotel_name;
    const projectId = projectNode.webProject.report_id;
    const timestamp = Date.now().toString();
    const pictureNumSuffix = timestamp.slice(-8);


    // 使用面板组的基本信息
    let materialLibraryName = "";
    let templateName = "";
    let templateNameIndex = "";

    if (currentPanelNode.value.panelInfo) {
      templateName = currentPanelNode.value.panelInfo.model_type || "";

      // 如果有系列信息，尝试获取文件名
      if (currentPanelNode.value.panelInfo.gang_series) {
        const series = seriesList.value.find(
          (s) =>
            `${s.Series}_${s.Version}` ===
            currentPanelNode.value.panelInfo.gang_series
        );
        if (series) {
          materialLibraryName = series.FileName;

          // 获取模型信息来设置 templateNameIndex
          const models = await fetchData("PanelSelection/ModelQuery", {
            FID: series.ID,
          });

          let matchedModel = null;

          // 优先使用面板组保存的模型信息
          if (currentPanelNode.value.panelInfo.model_id) {
            matchedModel = models.find(
              (model) => model.ID === currentPanelNode.value.panelInfo.model_id
            );
          }

          // 如果没有保存的模型ID，尝试通过其他条件匹配
          if (!matchedModel && currentPanelNode.value.panelInfo.model_type) {
            matchedModel = models.find(
              (model) =>
                model.ModelName === currentPanelNode.value.panelInfo.model_type
            );
          }

          // 如果还没有匹配，查找面板数匹配的模型
          if (!matchedModel) {
            const panelCount = currentPanelNode.value.panelInfo.panel_count;
            matchedModel = models.find(
              (model) => model.PanelCount === panelCount
            );
          }

          // 如果仍然没有匹配，选择面板数最小的模型
          if (!matchedModel && models.length > 0) {
            matchedModel = models.reduce((minModel, currentModel) => {
              return currentModel.PanelCount <
                (minModel?.PanelCount || Infinity)
                ? currentModel
                : minModel;
            });
          }

          if (matchedModel) {
            templateNameIndex = matchedModel.ShapeNumber;
            // 确保templateName使用模型的名称
            if (!currentPanelNode.value.panelInfo.model_type) {
              templateName = matchedModel.ModelName;
            }
          }
        }
      }
    }

    const patternList = [];

    // 获取Trench数据
    const Trench = await fetchData("PanelSelection/TrenchQuery", {
      MID: currentPanelNode.value.panelInfo.gang_material_id,
    });

    // 遍历面板配置，使用面板单元的数据构建预览对象
    for (let i = 0; i < panelConfigTable.value.length; i++) {
      const panelConfig = panelConfigTable.value[i];
      const locationList = [];

      if (panelConfig.panelUnitGuid && panelConfig.panelUnitData) {
        const panelUnit = panelConfig.panelUnitData;

        if (panelUnit.elements_json) {
          try {
            const elementsData = JSON.parse(panelUnit.elements_json);
            // 获取位置信息
            let locations = [];
            if (panelUnit.pattern_id) {
              locations = await getLocationls(panelUnit.pattern_id);
            }

            for (let j = 0; j < elementsData.length; j++) {
              const element = elementsData[j];
              const location = locations.find(
                (loc) => loc.ID === element.locationId
              );

              let shapeNumber = "";
              let fileName = "";
              let shapeType = 0;
              let shapeColor = element.backlightColor || "#FFFFFF";
              let shapeFont = element.font || "";
              let shapeFontSize = parseFloat(element.size) || 0.0;
              let lineNumber = "";

              if (element.content) {
                if (element.type === 1) {
                  // 图标类型
                  shapeType = 1;
                  const fileId = element.fileId || panelUnit.series_id;
                  if (fileId) {
                    const icons = await fetchData("PanelSelection/IconQuery", {
                      FID: fileId,
                    });
                    const icon = icons.find(
                      (icon) => icon.ShapeNumber === element.content
                    );
                    shapeNumber =
                      icon && icon.ShapeNumber != null
                        ? String(icon.ShapeNumber)
                        : String(element.content);

                    // 获取图标对应的文件名
                    if (icon && icon.FID) {
                      const iconSeries = seriesList.value.find(
                        (s) => s.ID === icon.FID
                      );
                      fileName = iconSeries ? iconSeries.FileName : "";
                    }
                  } else {
                    shapeNumber = String(element.content);
                  }
                } else {
                  // 文字类型
                  shapeType = 0;
                  shapeNumber = String(element.content);
                  shapeFont = element.font || "";
                  shapeFontSize = parseFloat(element.size) || 0.0;

                  // 解析行号
                  if (location && location.lineNumber) {
                    lineNumber = location.lineNumber.toString();
                  }
                }
              }

              let remark = "";
              if (element.type !== 1 && (element.font || element.size)) {
                remark = `${element.font || ""}_${element.size || ""}`;
                if (lineNumber) {
                  remark += `_${lineNumber}`;
                }
              }

              locationList.push({
                IndexNumber: element.indexNum.toString(),
                Remark: remark,
                ShapeNumber: shapeNumber,
                ShapeType: shapeType,
                FileName: fileName,
                ShapeColor: shapeColor,
                ShapeFont: shapeFont,
                ShapeFontSize: shapeFontSize,
                LineNumber:
                  element.lineNumber.toString() !== "0"
                    ? element.lineNumber.toString()
                    : "",
              });
            }
          } catch (error) {
            console.error("解析面板单元数据失败:", error);
          }
        }
      }

      // 获取Pattern的ShapeNumber（从tbl_pattern表）
      let shapeNumber = "";
      let fileName = "";

      if (panelConfig.panelUnitData && panelConfig.panelUnitData.pattern_id) {
        // 获取Pattern信息
        const patterns = await fetchData("PanelSelection/PatternQuery", {
          FID: panelConfig.panelUnitData.series_id,
        });

        const pattern = patterns.find(
          (p) => p.ID === panelConfig.panelUnitData.pattern_id
        );
        if (pattern) {
          shapeNumber = pattern.ShapeNumber || "";

          // 获取Pattern对应的文件名
          if (pattern.FID) {
            const patternSeries = seriesList.value.find(
              (s) => s.ID === pattern.FID
            );
            fileName = patternSeries ? patternSeries.FileName : "";
          }
        }
      }

      // 如果无法从Pattern获取，使用产品类型作为备用
      if (!shapeNumber && panelConfig.panelUnitData) {
        shapeNumber = panelConfig.panelUnitData.product_type || "";
      }

      const pindxn = Trench.find(
        (item) => item.TrenchName.split("_")[1] === (i + 1).toString()
      );

      patternList.push({
        IndexNumber: pindxn ? pindxn.IndexNum.toString() : (i + 1).toString(),
        ShapeNumber: shapeNumber,
        FileName: fileName,
        LocationList: locationList,
      });
    }

    // 解析LOGO配置
    let logoConfigValue = {};
    try {
      if (currentPanelNode.value.panelInfo.logo_json) {
        logoConfigValue = JSON.parse(
          currentPanelNode.value.panelInfo.logo_json
        );
      }
    } catch (error) {
      console.error("解析LOGO配置失败:", error);
      logoConfigValue = {};
    }

    var panelNode = currentPanelNode.value?.id.split('_').pop() || "";
    const pictureNum = `List_${hotel_name}_${panelNode}_${currentPanelNode.value.panelInfo.panel_list_name}_${pictureNumSuffix}`;

    // 构建完整的previewObject结构体
    const previewObject = {
      Guid: currentPanelNode.value.panelGuid,
      MaterialLibraryName: materialLibraryName || "未找到图库文件",
      PictureNum: pictureNum,
      Process: generateImage ? 0 : -1, // -1表示只生成结构体
      ProjectId: projectId || "未知项目ID",
      ProjectName: hotel_name || "未知酒店",
      TemplateName: templateName || "未找到模板",
      TemplateNameIndex: templateNameIndex || "未找到模板索引",
      User: currentUser || "未知用户",
      LogoPosition: logoConfigValue.LogoPosition || "",
      LogoFileName: logoConfigValue.LogoFileName || "",
      LogoIndexNumber: logoConfigValue.LogoIndexNumber || "",
      PatternList: patternList,
    };

    return previewObject;
  } catch (error) {
    console.error("生成面板组结构化数据失败:", error);
    return null;
  } finally {
    // 无论成功失败，都要重置标记
    isGeneratingStructureData.value = false;
  }
};
// ==================== LOGO相关方法 ====================
/**
 * 获取Logo列表
 */
const getLogoList = async () => {
  try {
    const logos = await fetchData("PanelSelection/LogoEnQuery");
    logoList.value = logos;
  } catch (error) {
    console.error("获取Logo列表失败:", error);
    logoList.value = [];
  }
};

/**
 * Logo位置选择变化处理
 */
const handleLogoPositionChange = (position) => {
  if (!selectedModel.value) {
    ElMessage.warning("请先选择模型");
    return;
  }

  // 根据选择的位置获取对应的LOGO索引号
  if (position === "left") {
    logoConfig.value.LogoIndexNumber =
      selectedModel.value.LOGO_L?.toString() || "";
  } else if (position === "right") {
    logoConfig.value.LogoIndexNumber =
      selectedModel.value.LOGO_R?.toString() || "";
  } else {
    logoConfig.value.LogoIndexNumber = "";
    logoConfig.value.LogoPosition = "";
    logoConfig.value.LogoFileName = "";
  }

  selectedLogoPosition.value = position;
  console.log(position, logoConfig.value)
  // 如果选择了"无图标"，清空选中的Logo
  if (position === "none") {
    selectedLogo.value = null;
    updateLogoConfig();
    return;
  }

  // 如果已经选择了LOGO，需要更新配置
  if (selectedLogo.value) {
    handleLogoChange(selectedLogo.value);
  } else {
    updateLogoConfig();
  }
};

/**
 * Logo选择变化处理
 */
const handleLogoChange = async (logo) => {
  if (!logo) {
    // 清空选择
    selectedLogo.value = null;
    logoConfig.value.LogoFileName = "";
    logoConfig.value.LogoPosition = "";
    updateLogoConfig();
    return;
  }

  try {
    selectedLogo.value = logo;

    logoConfig.value.LogoIndexNumber = logo.ShapeNumber || "";

    const logoFileName = await getLogoFileNameByFid(logo.FID);
    logoConfig.value.LogoFileName = logoFileName;

    if (!logoConfig.value.LogoPosition && selectedLogoPosition.value) {
      if (selectedLogoPosition.value === "left") {
        logoConfig.value.LogoPosition =
          selectedModel.value?.LOGO_L?.toString() || "";
      } else if (selectedLogoPosition.value === "right") {
        logoConfig.value.LogoPosition =
          selectedModel.value?.LOGO_R?.toString() || "";
      }
    }

    updateLogoConfig();
  } catch (error) {
    console.error("处理LOGO选择失败:", error);
    ElMessage.error("LOGO选择失败");
  }
};
/**
 * 根据FID从tbl_cdr_file获取FileName
 */
const getLogoFileNameByFid = async (fid) => {
  try {
    if (!fid) return "";

    // 方法1: 从本地缓存的seriesList中查找
    const series = seriesList.value.find((s) => s.ID === fid);
    if (series && series.FileName) {
      return series.FileName;
    }

    // 方法2: 如果本地没有，从数据库查询
    const cdrFiles = await fetchData("PanelSelection/SeriesQuery");
    const targetFile = cdrFiles.find((file) => file.ID === fid);

    return targetFile ? targetFile.FileName : "";
  } catch (error) {
    console.error("根据FID获取FileName失败:", error);
    return "";
  }
};
/**
 * 更新LOGO配置到表单
 */
const updateLogoConfig = () => {
  try {
    // 验证配置完整性
    const configToSave = { ...logoConfig.value };

    // 确保所有字段都有值
    configToSave.LogoPosition = configToSave.LogoPosition || "";
    configToSave.LogoFileName = configToSave.LogoFileName || "";
    configToSave.LogoIndexNumber = configToSave.LogoIndexNumber || "";

    // 序列化前验证
    if (typeof configToSave !== "object") {
      throw new Error("LOGO配置必须是对象");
    }

    newPanelForm.value.logo_json = JSON.stringify(configToSave);
  } catch (error) {
    console.error("更新LOGO配置失败:", error);
    // 失败时保存空对象
    newPanelForm.value.logo_json = "{}";
    ElMessage.error("LOGO配置更新失败");
  }
};

/**
 * 从保存的数据中恢复LOGO配置
 */
const restoreLogoConfig = async (panelInfo) => {
  if (!panelInfo || !panelInfo.logo_json) {
    logoConfig.value = {
      LogoPosition: "",
      LogoFileName: "",
      LogoIndexNumber: "",
    };
    selectedLogoPosition.value = "";
    selectedLogo.value = null;
    return;
  }

  try {
    const savedConfig = JSON.parse(panelInfo.logo_json);

    // 恢复基本配置
    logoConfig.value = { ...savedConfig };

    // 恢复位置选择器 - 增强容错逻辑
    if (savedConfig.LogoPosition) {
      // 方法1: 通过LogoPosition直接设置
      if (
        savedConfig.LogoPosition === "left" ||
        savedConfig.LogoPosition === "right"
      ) {
        selectedLogoPosition.value = savedConfig.LogoPosition;
      }
      // 方法2: 通过模型推断位置
      else if (selectedModel.value) {
        if (
          savedConfig.LogoPosition === selectedModel.value.LOGO_L?.toString()
        ) {
          selectedLogoPosition.value = "left";
        } else if (
          savedConfig.LogoPosition === selectedModel.value.LOGO_R?.toString()
        ) {
          selectedLogoPosition.value = "right";
        } else {
          // 无法推断，清空位置选择
          selectedLogoPosition.value = "";
        }
      } else {
        // 没有模型信息，尝试直接使用保存的值
        selectedLogoPosition.value = savedConfig.LogoPosition;
      }
    } else {
      selectedLogoPosition.value = "";
    }

    // 恢复LOGO选择 - 增强容错逻辑
    if (savedConfig.LogoFileName && savedConfig.LogoPosition) {
      // 确保LOGO列表已加载
      if (logoList.value.length === 0) {
        await getLogoList();
      }

      // 查找匹配的LOGO - 改进匹配逻辑
      let matchedLogo = null;

      // 方法1: 通过ShapeNumber匹配
      if (savedConfig.LogoIndexNumber) {
        matchedLogo = logoList.value.find(
          (logo) => logo.ShapeNumber === savedConfig.LogoIndexNumber
        );
      }

      // 方法2: 通过位置信息匹配
      if (!matchedLogo && savedConfig.LogoPosition) {
        matchedLogo = logoList.value.find(
          (logo) => logo.ShapeNumber === savedConfig.LogoPosition
        );
      }

      if (matchedLogo) {
        selectedLogo.value = matchedLogo;
      } else {
        console.warn("未找到匹配的LOGO，保存的配置:", savedConfig);
        selectedLogo.value = null;
      }
    } else {
      selectedLogo.value = null;
    }

    // 更新LOGO配置到表单
    updateLogoConfig();
  } catch (error) {
    console.error("恢复LOGO配置失败:", error);
    // 失败时使用默认配置
    logoConfig.value = {
      LogoPosition: "",
      LogoFileName: "",
      LogoIndexNumber: "",
    };
    selectedLogoPosition.value = "";
    selectedLogo.value = null;
    ElMessage.warning("LOGO配置记录获取失败，请手动设置");
  }
};
// ==================== 背光相关方法 ====================

/**
 * 处理背光开关切换
 */
const handleBacklightToggle = (row, index) => {
  if (row.backlightEnabled) {
    // 启用背光，设置默认颜色
    row.backlightColor = "#F19947";
  } else {
    // 禁用背光，设置为白色
    row.backlightColor = "#FFFFFF";
  }

  // 更新该行所有相关元素的背光颜色
  updateRowBacklight(row);
  savePanelUnitConfig(); // 自动保存
};


/**
 * 更新整行的背光颜色
 */
const updateRowBacklight = (row) => {
  // 更新合并表单中的背光设置
  if (row.icon) {
    row.icon.backlightColor = row.backlightColor;
    row.icon.backlightEnabled = row.backlightEnabled;
  }
  if (row.chinese) {
    row.chinese.backlightColor = row.backlightColor;
    row.chinese.backlightEnabled = row.backlightEnabled;
  }
  if (row.english) {
    row.english.backlightColor = row.backlightColor;
    row.english.backlightEnabled = row.backlightEnabled;
  }

  // 同步更新 panelUnitForm 中的数据
  syncBacklightToPanelUnitForm(row);
};

/**
 * 将背光设置同步到 panelUnitForm
 */
const syncBacklightToPanelUnitForm = (mergedRow) => {
  if (!mergedRow.locations || !Array.isArray(mergedRow.locations)) return;

  mergedRow.locations.forEach((location) => {
    const targetItem = panelUnitForm.value.find(
      (item) =>
        item.locationId === location.locationId || item.id === location.id
    );
    if (targetItem) {
      targetItem.backlightColor = mergedRow.backlightColor;
      targetItem.backlightEnabled = mergedRow.backlightEnabled;
    }
  });
};

// ==================== 字体相关方法 ====================

/**
 * 获取字体列表
 */
const getFont = async () => {
  try {
    const fonts = await fetchData("PanelSelection/FontQuery", {});
    fontList.value = fonts;
    return fonts;
  } catch (error) {
    console.error("获取字体列表失败:", error);
    return [];
  }
};
// ==================== watch监听器 ====================
/**
 * 监听单个面板配置变化，自动保存到remark字段
 */
watch(
  () => mergedPanelUnitForm.value,
  async (newForm, oldForm) => {
    // 如果正在生成结构化数据，不触发操作，避免无限循环
    if (
      isGeneratingStructureData.value ||
      !currentPanelUnit.value ||
      !newForm ||
      newForm.length === 0
    )
      return;

    try {
      // 防抖处理，避免频繁保存
      if (window.panelUnitSaveTimeout) {
        clearTimeout(window.panelUnitSaveTimeout);
      }

      window.panelUnitSaveTimeout = setTimeout(async () => {
        // 只有在用户编辑时才执行保存和预览刷新
        if (isUserEditingPanelUnit.value) {
          await autoSavePanelUnitConfig();
          await refreshPanelGroupPreview();
          await refreshPanelUnitPreview();
        }

        // 刷新预览后，恢复之前选中的行
        nextTick(() => {
          if (currentMergedPanelUnitRow.value && mergedPanelUnitTable.value) {
            // 尝试通过locationName找到对应的行
            const targetRow = newForm.find(
              (row) =>
                row.locationName ===
                currentMergedPanelUnitRow.value.locationName
            );
            if (targetRow) {
              // 使用表格的setCurrentRow方法设置当前行
              mergedPanelUnitTable.value.setCurrentRow(targetRow);
              currentMergedPanelUnitRow.value = targetRow;
            }
          }
        });
      }, 50); // 防抖
    } catch (error) {
      console.error("监听面板单元配置变化失败:", error);
    }
  },
  { deep: true, immediate: false }
);

// 标记是否正在生成面板组结构化数据，用于避免无限循环
const isGeneratingStructureData = ref(false);

/**
 * 监听面板组配置变化，自动保存到remark字段并清空预览
 */
watch(
  () => panelConfigTable.value,
  async (newConfig, oldConfig) => {
    // 如果正在生成结构化数据，不触发自动保存，避免无限循环
    if (
      isGeneratingStructureData.value ||
      !currentPanelNode.value ||
      !newConfig ||
      newConfig.length === 0
    )
      return;
    try {
      // 防抖处理
      if (window.panelGroupSaveTimeout) {
        clearTimeout(window.panelGroupSaveTimeout);
      }
      window.panelGroupSaveTimeout = setTimeout(async () => {
        await autoSavePanelGroupConfig();
      }, 100); // 防抖
    } catch (error) {
      console.error("监听面板组配置变化失败:", error);
    }
  },
  { deep: true, immediate: false }
);

watch(
  [currentPanelNode, currentPanelUnitObj],
  () => {
    managePolling();
  },
  { deep: true }
);
// 持久化 selectedProjectId 到 localStorage
watch(selectedProjectId, (val) => {
  try {
    if (val === null || val === undefined || val === "") {
      localStorage.removeItem("selectedProjectId");
    } else {
      localStorage.setItem("selectedProjectId", String(val));
    }
  } catch (e) {
    // ignore
  }
});

// 持久化 currentPanelUnit
watch(currentPanelUnit, (val) => {
  try {
    if (!val) {
      localStorage.removeItem("currentPanelUnit");
    } else {
      localStorage.setItem("currentPanelUnit", String(val));
    }
  } catch (e) {
    // ignore
  }
});
// 监听 panelUnitForm 变化，重新构建合并数据
watch(
  panelUnitForm,
  () => {
    buildMergedPanelUnitForm();
  },
  { deep: true }
);

watch(selectedSeriesForUnit, async (newSeries, oldSeries) => {
  if (newSeries) {
    try {
      // 先重置选择器
      selectedDirectionForUnit.value = "";
      selectedColorForUnit.value = "";
      selectedPatternForUnit.value = "";
      selectedModelForUnit.value = null;
      // 加载数据
      await getModelsForUnit(newSeries.ID);
      await getPatternsForUnit(newSeries.ID);

      // 如果是编辑模式，恢复之前的选择
      if (isEditPanelUnit.value && currentEditPanelUnit.value) {
        await restoreSelectionsAfterSeriesLoad();
      }
    } catch (error) {
      console.error("加载系列数据失败:", error);
    }
  } else {
    // 重置选择器
    selectedDirectionForUnit.value = "";
    selectedColorForUnit.value = "";
    selectedPatternForUnit.value = "";
    selectedModelForUnit.value = null;
    directionOptionsForUnit.value = [];
    colorOptionsForUnit.value = [];
    patternsListForUnit.value = [];
  }
}, { deep: true });

// 监听selectedPatternForUnit的变化，触发updateModelListForUnit方法
watch(selectedPatternForUnit, (newPattern, oldPattern) => {
  if (newPattern) {
    updateModelListForUnit();
  }
});
// ==================== 初始化 ====================

/**
 * 页面加载完成后的初始化
 */
onMounted(async () => {
  const startTime = Date.now();
  showLoading("页面加载中...");

  try {
    const isNew = await localHttp.post("Huoban/GetAllProjectReportData");
    if (isNew.data.isok) {
      console.log(isNew.data.message);
    }
    await getProject();
    const data = await fetchData("PanelSelection/SeriesQuery");
    seriesList.value = data;
    await getFont();
    await getIconLibraries();
    await getLogoList();
    // 尝试从 localStorage 恢复用户上次的选择（按顺序恢复 project -> tree -> panelUnit）
    await restoreSelectionsFromLocalStorage();
  } catch (error) {
    console.error("初始化失败:", error);
    ElMessage.error("页面加载失败");
  } finally {
    const elapsed = Date.now() - startTime;
    const delay = Math.max(0, 1000 - elapsed);
    setTimeout(hideLoading, delay);
  }
});
onUnmounted(() => {
  stopPolling();
  // 清理防抖定时器
  if (window.panelUnitSaveTimeout) {
    clearTimeout(window.panelUnitSaveTimeout);
  }
  if (window.panelGroupSaveTimeout) {
    clearTimeout(window.panelGroupSaveTimeout);
  }
});
</script>

<style scoped>
/* 容器布局 */
.container {
  display: flex;
  height: 100%;
  padding: 5px;
  gap: 8px;
  background-color: #f5f7fa;
}

/* 左侧面板 */
.left-panel {
  flex: 3;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

/* 右侧面板 */
.right-panel {
  flex: 9;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

/* 面板区域高度分配 */
.left-top {
  height: 3%;
}

.left-bottom {
  height: 97%;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.right-middle,
.right-bottom {
  height: 50%;
}

/* 树组件样式 */
.full-height-tree {
  height: 100%;
  overflow: auto;
}

.left-bottom-bottom {
  height: 50%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.left-bottom-bottom .section-header {
  padding: 5px;
  border-bottom: 1px solid #e0e0e0;
  background: #f8f9fa;
  margin: 0;
}

.left-bottom-bottom .table-content {
  flex: 1;
  overflow: auto;
}

.left-bottom-dynamic-list {
  height: 30%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.left-bottom-dynamic-list .section-header {
  padding: 0px;
  border-bottom: 1px solid #e0e0e0;
  background: #f8f9fa;
  margin: 0;
}

.left-bottom-dynamic-list .table-content {
  flex: 1;
  padding: 0px;
  overflow: auto;
}

.left-bottom-top {
  height: 77%;
  overflow: hidden;
}

/* 树节点样式 */
.tree-node-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.tree-node-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tree-node-actions {
  display: flex;
  gap: 5px;
}

/* 详情弹窗样式 */
.details {
  margin-top: 4px;
  border-radius: 6px;
  overflow: hidden;
  font-size: 0.85rem;
}

/* 对话框样式 */
.dialog-content {
  display: flex;
  gap: 15px;
  height: 500px;
  margin-bottom: 10px;
}

.dialog-left,
.dialog-middle,
.dialog-right {
  display: flex;
  flex-direction: column;
}

.dialog-left {
  flex: 1;
}

.dialog-middle {
  flex: 2;
}

.dialog-right {
  flex: 3;
}

.dialog-bottom {
  border-top: 1px solid #e0e0e0;
  padding-top: 10px;
}

/* 模型选择器样式 */
.model-selectors {
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 5px;
  background: #f8f9fa;
  border-radius: 6px;
  height: 100%;
}

.selector-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.selector-row .el-select:disabled {
  opacity: 0.6;
}

.selector-row .el-select:not(:disabled) {
  border-color: #409eff;
}

.selector-label {
  width: 100px;
  font-weight: bold;
  color: #606266;
}

/* 区域标题样式 */
.section-title {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #303133;
  text-align: center;
}

/* 预览容器样式 */
.preview-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: #f8f9fa;
  border-radius: 6px;
  padding: 5px;
  height: 100%;
  overflow: hidden;
}

.preview-container .preview-image {
  flex: 1;
  min-height: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.preview-info {
  margin-top: 5px;
  text-align: left;
  background: white;
  padding: 5px;
  border-radius: 4px;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.preview-info p {
  margin: 5px 0;
  font-size: 14px;
}

/* 面板配置容器 */
.panel-unit-config-container {
  display: flex;
  height: 100%;
  gap: 0;
  /* 移除内部间隙 */
  border: 1px solid #e0e0e0;
  /* 添加外部边框 */
  border-radius: 6px;
  overflow: hidden;
  background: white;
}

/* 通用区域样式 */
.preview-section-top,
.preview-section-down,
.table-section,
.form-section {
  border: none;
  border-radius: 0;
  box-shadow: none;
  border-right: 1px solid #e0e0e0;
}

.table-section,
.form-section {
  flex: 8;
}

.preview-section-top {
  flex: 10;
}

.preview-section-down {
  flex: 3;
}

/* 区域头部样式 */
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px;
  border-bottom: 1px solid #e0e0e0;
  background: #f8f9fa;
  margin: 0;
}

.section-header span {
  font-size: 16px;
  font-weight: bold;
  color: #303133;
}

/* 内容区域样式 */
.preview-content,
.table-content,
.form-content {
  flex: 1;
  padding: 5px;
  overflow: hidden;
}

.left-bottom-bottom .table-content {
  padding: 0px;
}

.preview-content {
  height: 39.8vh;
  /*calc(100vh - 570px);*/
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  padding: 5px;
  box-sizing: border-box;
}

/* 预览图片样式 */
.preview-image {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  position: relative;
}

.preview-image>* {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.preview-image img {
  max-width: 100%;
  max-height: 220px;
  object-fit: contain;
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.preview-image .el-image {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.preview-image .el-image img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* 占位符样式 */
.preview-placeholder,
.empty-prompt {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  color: #909399;
  background: #f8f9fa;
  border-radius: 4px;
  border: 1px dashed #dcdfe6;
}

.empty-prompt {
  background: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.empty-prompt p {
  margin-top: 10px;
  font-size: 16px;
}

/* 图标选择对话框样式 */
.icon-select-dialog {
  height: 100%;
  overflow-y: auto;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 10px;
}

.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 10px;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.icon-item:hover {
  border-color: #409eff;
  background-color: #f5f7fa;
}

.icon-preview {
  margin-bottom: 5px;
}

.icon-name {
  font-size: 12px;
  text-align: center;
  word-break: break-all;
}

/* 表单内容区域调整 */
.form-content {
  flex: 1;
  padding: 5px;
  overflow: auto;
}

/* 图标库选择器样式 */
.icon-library-selector {
  margin-bottom: 20px;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.icon-library-table-container {
  display: inline-block;
  vertical-align: middle;
}

.selector-label {
  font-weight: bold;
  color: #606266;
}

/* 图标搜索框样式 */
.icon-search-input {
  flex: 1;
  max-width: 300px;
}

/* 图标网格容器 */
.icon-grid-container {
  max-height: calc(100vh - 110px);
  overflow-y: auto;
  display: flex;
  gap: 15px;
}

/* 图标库表格容器 */
.icon-library-table-container {
  height: calc(100vh - 150px);
  width: 150px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  overflow: hidden;
}

.icon-library-title {
  padding: 8px 12px;
  background: #f8f9fa;
  border-bottom: 1px solid #e0e0e0;
  font-weight: bold;
  color: #606266;
  text-align: center;
}

/* 图标网格包装器 */
.icon-grid-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* 图标项样式调整 */
.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 15px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s;
  background: white;
}

.icon-item:hover {
  border-color: #409eff;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.icon-library {
  font-size: 11px;
  color: #909399;
  margin-top: 5px;
  text-align: center;
}

/* 空状态样式 */
.empty-icons {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 200px;
  color: #909399;
}

.empty-icons p {
  margin-top: 10px;
}

/* 图标网格布局优化 */
.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 15px;
  padding: 10px;
}

/* 背光控制样式 */
.backlight-control {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* 颜色选择器样式调整 */
.backlight-control .el-color-picker {
  vertical-align: middle;
}

.logo-config-section {
  margin-top: 15px;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e0e0e0;
}

.logo-config-section .section-title {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #606266;
  text-align: left;
}

/* 图标预览单元格样式 */
.icon-preview-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: #f5f7fa;
  color: #909399;
}

/* 新增：表格和预览图的上下布局 */
.table-preview-container {
  display: flex;
  flex-direction: column;
  height: calc(100% - 40px);
}

.preview-below-table {
  height: 24vh;
  border-top: 1px solid #e0e0e0;
  display: flex;
  flex-direction: column;
}

.preview-below-table .preview-content {
  height: calc(100% - 0px);
  /* 减去header高度 */
  flex: 1;
}

/* 新增：表单内容的左右布局 */
.form-content-container {
  display: flex;
  height: 39.8vh;
  gap: 0px;
}

.pattern-preview-section {
  width: 30%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.pattern-preview-section .section-header {
  padding: 5px;
  border-bottom: 1px solid #e0e0e0;
  background: #f8f9fa;
  margin: 0;
  text-align: center;
}

.pattern-preview-section .preview-content {
  flex: 1;
  padding: 5px;
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 调整表格区域宽度 */
.form-section .table-content {
  width: 70%;
}

/* 确保预览图容器正确显示 */
.preview-below-table .preview-image,
.pattern-preview-section .preview-image {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.preview-below-table .preview-image .el-image,
.pattern-preview-section .preview-image .el-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
</style>
