前端懒加载改造指南.md 7.5 KB

质控结果详情页 - 前端懒加载改造指南

✅ 已完成的后端修改

  1. 主接口改为极速版/api/qc/result/detail/{taskId}/{studyId}

    • 只返回基础信息(任务、检查、患者、整体质控结果)
    • 不再返回 imageResultslogs
  2. 新增懒加载接口

    • /api/qc/result/image-results/{taskId}/{studyId} - 查询图像结果
    • /api/qc/result/execution-logs/{taskId}/{studyId} - 查询执行日志
    • /api/qc/result/image-factors/{taskId}/{studyId} - 查询单张图像的因子

🔧 前端必须修改的地方

文件:src/views/QcResultDetail.vue

第1步:添加状态变量(已完成✅)

在数据状态部分添加:

// 懒加载状态
const imageResults = ref<any[]>([]) // 图像结果(懒加载)
const imageResultsLoading = ref(false) // 图像结果加载状态
const executionLogs = ref<any[]>([]) // 执行日志(懒加载)
const executionLogsLoading = ref(false) // 执行日志加载状态
const imageResultsLoaded = ref(false) // 图像结果是否已加载
const executionLogsLoaded = ref(false) // 执行日志是否已加载

第2步:添加懒加载函数

loadData() 函数后面添加:

// 【懒加载】加载图像结果
const handleLoadImageResults = async () => {
  if (imageResultsLoaded.value) {
    console.log('图像结果已加载,跳过')
    return
  }

  imageResultsLoading.value = true
  try {
    const taskId = route.query.taskId as string
    const studyId = route.query.studyId as string
    const examItemName = route.query.examItemName as string

    const response = await loadImageResults(taskId, studyId, examItemName, false)

    if (response.code === 200 && response.data) {
      imageResults.value = response.data
      imageResultsLoaded.value = true
      console.log('✅ 图像结果加载成功,数量:', imageResults.value.length)
    } else {
      ElMessage.error(response.message || '加载图像结果失败')
    }
  } catch (error: any) {
    console.error('加载图像结果失败:', error)
    ElMessage.error(error.message || '加载图像结果失败')
  } finally {
    imageResultsLoading.value = false
  }
}

// 【懒加载】加载执行日志
const handleLoadExecutionLogs = async () => {
  if (executionLogsLoaded.value) {
    console.log('执行日志已加载,跳过')
    return
  }

  executionLogsLoading.value = true
  try {
    const taskId = route.query.taskId as string
    const studyId = route.query.studyId as string

    const response = await loadExecutionLogs(taskId, studyId)

    if (response.code === 200 && response.data) {
      executionLogs.value = response.data
      executionLogsLoaded.value = true
      console.log('✅ 执行日志加载成功,数量:', executionLogs.value.length)
    } else {
      ElMessage.error(response.message || '加载执行日志失败')
    }
  } catch (error: any) {
    console.error('加载执行日志失败:', error)
    ElMessage.error(error.message || '加载执行日志失败')
  } finally {
    executionLogsLoading.value = false
  }
}

第3步:添加Tab切换监听

onMounted() 前面添加:

// 监听Tab切换,触发懒加载
watch(activeTab, (newTab) => {
  console.log('Tab切换到:', newTab)

  if (newTab === 'image' && !imageResultsLoaded.value) {
    // 切换到图像结果Tab,且未加载过,触发懒加载
    handleLoadImageResults()
  } else if (newTab === 'logs' && !executionLogsLoaded.value) {
    // 切换到执行日志Tab,且未加载过,触发懒加载
    handleLoadExecutionLogs()
  }
})

第4步:修改模板显示逻辑

在模板中找到"图像质控结果"Tab,修改显示逻辑:

修改前(约424行):

<el-tab-pane label="图像质控结果" name="image">
  <div v-if="activeTab === 'image' && imageResults.length > 0">
    <!-- 图像结果展示 -->
  </div>
  <el-empty v-else description="暂无图像质控结果" />
</el-tab-pane>

修改后:

<el-tab-pane label="图像质控结果" name="image">
  <!-- 加载状态 -->
  <div v-if="imageResultsLoading" class="loading-container">
    <el-skeleton :rows="5" animated />
  </div>

  <!-- 已加载状态 -->
  <div v-else-if="imageResults.length > 0">
    <!-- 图像结果展示(原有代码) -->
  </div>

  <!-- 未加载状态 -->
  <div v-else class="load-tip-container">
    <el-empty description="点击下方按钮加载图像质控结果">
      <el-button type="primary" @click="handleLoadImageResults">
        加载图像结果
      </el-button>
    </el-empty>
  </div>
</el-tab-pane>

同样修改"执行日志"Tab(约329行):

<el-tab-pane label="执行日志" name="logs">
  <!-- 加载状态 -->
  <div v-if="executionLogsLoading" class="loading-container">
    <el-skeleton :rows="5" animated />
  </div>

  <!-- 已加载状态 -->
  <div v-else-if="executionLogs.length > 0">
    <!-- 执行日志展示(原有代码) -->
  </div>

  <!-- 未加载状态 -->
  <div v-else class="load-tip-container">
    <el-empty description="点击下方按钮加载执行日志">
      <el-button type="primary" @click="handleLoadExecutionLogs">
        加载执行日志
      </el-button>
    </el-empty>
  </div>
</el-tab-pane>

第5步:修改detailData引用

由于后端不再返回 imageResultslogs,需要将所有引用改为新添加的状态变量:

查找并替换:

  • detailData.value.imageResultsimageResults.value
  • detailData.value.logsexecutionLogs.value
  • multiPartData.value.logsexecutionLogs.value

📝 完整的修改检查清单

  • 1. 添加状态变量(已完成✅)
  • 2. 添加 handleLoadImageResults 函数
  • 3. 添加 handleLoadExecutionLogs 函数
  • 4. 添加 watch(activeTab, ...) 监听Tab切换
  • 5. 修改"图像质控结果"Tab模板
  • 6. 修改"执行日志"Tab模板
  • 7. 替换所有 detailData.value.imageResultsimageResults.value
  • 8. 替换所有 detailData.value.logsexecutionLogs.value

🚀 测试步骤

  1. 重启前端开发服务器:npm run dev
  2. 访问质控结果详情页
  3. 预期效果
    • 页面瞬间加载(< 500ms),只显示基础信息和整体质控结果
    • 切换到"图像质控结果"Tab,自动触发懒加载
    • 切换到"执行日志"Tab,自动触发懒加载
    • 第二次切换Tab,直接显示缓存数据(不重新加载)

💡 优化建议

如果希望进一步优化用户体验,可以:

  1. 添加预加载提示

    <div class="load-tip">
     <el-icon><InfoFilled /></el-icon>
     <span>数据较大,切换Tab时自动加载</span>
    </div>
    
    1. 显示加载进度vue <el-progress v-if="imageResultsLoading" :percentage="50" />
  2. 使用骨架屏代替Loading

    <el-skeleton v-if="imageResultsLoading" :rows="5" animated />
    

    ⚠️ 注意事项

    1. 多部位检查的图像结果:目前代码可能还需要适配多部位检查,需要从 multiPartData 中获取对应部位的图像结果

    2. 日志数据获取:对于多部位检查,执行日志可能需要从 multiPartData.value.logs 获取

    3. 向后兼容:如果后端还返回 imageResultslogs,前端代码可以先用判断:

      // 兼容旧版本后端
      if (detailData.value.imageResults) {
      imageResults.value = detailData.value.imageResults
      imageResultsLoaded.value = true
      }