13 KiB
13 KiB
调试记录
特殊参数显示问题
问题描述
在数据管理页面中,装备详情对话框的特殊参数部分显示为空行或不显示。
调试步骤
- 后端数据查询
# 测试特殊参数查询
SELECT equipment_id, param_name, param_value, param_unit
FROM custom_params
WHERE param_name IS NOT NULL
AND param_value IS NOT NULL
LIMIT 5
- 日志记录
logging.info(f"Getting details for equipment ID: {id}")
logging.info(f"Equipment type: {equipment_type}")
logging.info(f"Found equipment details: {result['name']}")
logging.info(f"Custom params: {result.get('custom_params')}")
- 前端调试
console.log('Requesting details for row:', row)
console.log('Details response:', response.data)
console.log('Custom params:', response.data.custom_params)
console.log('Selected data:', selectedData.value)
关键发现
- 数据库查询
- 特殊参数表中有数据
- JSON_ARRAYAGG 返回的格式需要处理
- 需要过滤掉 NULL 值
- 数据格式
- 后端返回的特殊参数是 JSON 字符串
- 需要在前端解析为数组
- 确保数组不为空
- 前端渲染
- 条件判断需要更严格
- 需要确保数据类型正确
- 需要正确格式化显示值
解决方案
- 后端查询优化
(
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'id', csp.id,
'param_name', csp.param_name,
'param_value', csp.param_value,
'param_unit', csp.param_unit,
'description', csp.description
)
)
FROM custom_params csp
WHERE csp.equipment_id = e.id
AND csp.param_name IS NOT NULL
AND csp.param_value IS NOT NULL
) as custom_params
- 前端数据处理
// 确保 custom_params 是数组
if (typeof response.data.custom_params === 'string') {
response.data.custom_params = JSON.parse(response.data.custom_params)
}
- 渲染条件优化
<template v-if="selectedData?.custom_params && Array.isArray(selectedData.custom_params) && selectedData.custom_params.length > 0">
最佳实践
- 数据库查询
- 使用子查询而不是 JOIN 获取特殊参数
- 确保返回格式统一
- 过滤无效数据
- 数据处理
- 统一数据格式
- 处理空值和异常
- 保持类型一致
- 前端显示
- 严格的条件判断
- 类型检查
- 格式化显示
- 调试方法
- 使用日志跟踪数据流
- 检查数据格式和类型
- 验证每个环节的数据
编辑对话框问题
问题描述
在数据管理页面中,编辑对话框的成本信息分区和特殊参数分区显示不正确。
调试步骤
- 检查数据流
console.log('Editing row:', row)
console.log('Edit data response:', response.data)
console.log('Parsed custom params:', data.custom_params)
console.log('Edit form data:', editForm.value)
- 检查模板结构
<!-- 错误的嵌套结构 -->
<el-form>
<template>
<el-divider>成本信息</el-divider>
</template>
</el-form>
<!-- 正确的结构 -->
<el-divider>成本信息</el-divider>
<el-form>
<!-- 表单项 -->
</el-form>
关键发现
- 模板结构问题
- el-divider 不应该嵌套在 template 中
- 每个分区需要独立的 el-form
- 避免不必要的 template 嵌套
- 数据类型问题
- 后端返回的数值是字符串类型
- el-input-number 组件需要数值类型
- 需要在前端进行类型转换
- 条件渲染问题
- v-if 条件过于严格可能导致内容不显示
- 某些字段应该始终显示
- 某些字段只在有值时显示
解决方案
- 修改模板结构
<!-- 成本信息 -->
<el-divider content-position="left">成本信息</el-divider>
<el-form :model="editForm" label-width="120px">
<el-form-item label="实际成本(元)">
<el-input-number v-model="editForm.actual_cost"></el-input-number>
</el-form-item>
</el-form>
- 数据类型转换
// 转换所有数值类型字段
Object.keys(data).forEach(key => {
if (isNumberInput(key) && data[key] !== null && data[key] !== undefined) {
data[key] = Number(data[key])
}
})
- 优化条件渲染
<!-- 始终显示必要字段 -->
<el-form-item label="实际成本(元)">
<el-input-number v-model="editForm.actual_cost"></el-input-number>
</el-form-item>
<!-- 只在有值时显示可选字段 -->
<el-form-item label="预测成本(元)" v-if="editForm.predicted_cost">
<el-input-number v-model="editForm.predicted_cost" disabled></el-input-number>
</el-form-item>
最佳实践
- 模板结构
- 保持清晰的分区结构
- 避免不必要的嵌套
- 使用合适的组件层级
- 数据处理
- 在获取数据后立即进行类型转换
- 确保数据类型与组件要求匹配
- 处理好空值和未定义值
- 条件渲染
- 合理使用 v-if 和 v-show
- 必要字段始终显示
- 可选字段根据条件显示
- 调试方法
- 使用 console.log 跟踪数据流
- 检查组件的属性要求
- 验证数据类型和结构
特征分析功能问题
问题描述
特征分析页面中,第一次点击分析按钮时,图表不显示,只有标题栏。第二次点击才能正常显示图表。
调试步骤
- 检查数据流
console.log('Analysis result:', analysisResult.value)
console.log('Charts not ready:', {
importanceChartRef: !!importanceChartRef.value,
correlationChartRef: !!correlationChartRef.value,
analysisResult: !!analysisResult.value
})
- 检查渲染时机
// 使用 watch 监听分析结果变化
watch(() => analysisResult.value, async (newResult) => {
if (newResult) {
await nextTick()
setTimeout(() => {
renderCharts()
}, 100)
}
}, { deep: true })
- 检查图表实例管理
// 销毁旧的图表实例
if (importanceChart.value) {
importanceChart.value.dispose()
}
if (correlationChart.value) {
correlationChart.value.dispose()
}
关键发现
- 渲染时机问题
- DOM 元素可能还未准备好
- 数据更新后需要等待 DOM 更新
- 需要正确管理图表实例
- 图表实例管理
- 需要保存图表实例的引用
- 重新渲染前需要销毁旧实例
- 组件卸载时需要清理实例
- 数据格式问题
- 特征名称需要中文映射
- 相关性数据需要保留2位小数
- 需要正确处理缺失值
解决方案
- 优化渲染逻辑
// 使用 nextTick 和延时确保 DOM 已更新
await nextTick()
setTimeout(() => {
renderCharts()
}, 100)
- 完善图表实例管理
// 保存图表实例的引用
const importanceChart = ref(null)
const correlationChart = ref(null)
// 组件卸载时清理
onUnmounted(() => {
importanceChart.value?.dispose()
correlationChart.value?.dispose()
})
- 优化数据处理
// 使用中文特征名
chinese_feature_names = [self.feature_names_map.get(name, name) for name in feature_names]
// 保留2位小数
correlation_data.append([
i, j,
round(correlation_matrix[i][j], 2)
])
最佳实践
- 渲染控制
- 使用 watch 监听数据变化
- 使用 nextTick 等待 DOM 更新
- 添加适当的延时确保渲染
- 实例管理
- 保存图表实例引用
- 及时销毁旧实例
- 组件卸载时清理
- 数据处理
- 统一使用中文特征名
- 控制数值精度
- 处理好缺失值
- 调试方法
- 添加详细的日志记录
- 检查 DOM 元素状态
- 验证数据格式
页面状态保持问题
问题描述
特征分析<EFBFBD><EFBFBD><EFBFBD>面切换到其他页面后再返回,页面状态(分析结果和图表)会丢失,需要重新分析。
调试步骤
- 检查路由配置
// 错误的配置
<keep-alive include="AnalysisPage">
<router-view></router-view>
</keep-alive>
// 正确的配置
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" :key="$route.fullPath" />
</keep-alive>
</router-view>
- 检查组件定义
// 错误的组件名称定义
<script setup name="AnalysisPage">
// 正确的组件名称定义
const __name = 'AnalysisPage'
关键发现
- keep-alive 配置问题
- 需要使用 v-slot API
- 需要使用动态组件
- 需要添加 key 属性
- 组件定义问题
- setup 语法糖不支持直接添加 name
- 需要使用 __name 或 defineOptions
- 缓存范围问题
- 不需要指定 include 属性
- 缓存所有路由组件更简单
- 避免组件名称不匹配的问题
解决方案
- 修改路由视图配置
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" :key="$route.fullPath" />
</keep-alive>
</router-view>
- 修改组件定义
const __name = 'AnalysisPage'
最佳实践
- 路由配置
- 使用 Vue3 的新 API
- 保持配置简单清晰
- 避免不必要的限制
- 组件定义
- 使用推荐的方式定义组件名
- 避免使用已废弃的语法
- 保持代码一致性
- 状态管理
- 合理使用 keep-alive
- 正确处理组件生命周期
- 注意清理工作
- 调试方法
- 检查组件是否被缓存
- 验证状态是否保持
- 确认生命周期钩子的执行
代码修改最佳实践
1. 修改前的准备
- 检查相关文件:
前端组件修改时检查:
- 相关的路由配置
- 父子组件关系
- 共用的组件和函数
- API调用
后端接口修改时检查:
- 路由定义
- 数据库查询
- 相关的工具类和函数
- 错误处理
- 保持命名一致性:
- 类名:ModelTrainer 而不是 ModelTraining
- 文件名:train_model.py 对应 ModelTrainer
- 变量名:保持前后端一致的命名规范
- 添加日志记录:
# 在关键节点添加日志
logging.info(f"Starting model training for {equipment_type}")
logging.info(f"Training dataset: {train_dataset_id}")
logging.error(f"Error in model training: {str(e)}")
2. 修改过程中
- 错误处理:
try:
# 主要逻辑
except Exception as e:
logging.error(f"Error: {str(e)}")
logging.error("Detailed traceback:", exc_info=True)
return jsonify({'error': str(e)}), 500
- 数据验证:
# 验证输入
if not formData.value.type:
throw new Error('请选择装备类型')
if not formData.value.train_dataset_id:
throw new Error('请选择训练数据集')
- 状态管理:
// 重置状态
formData.value.train_dataset_id = null
formData.value.validation_dataset_id = null
trainingResult.value = null
3. 修改后的验证
- 功能测试:
- 验证主要功能
- 测试边界条件
- 检查错误处理
- 性能检查:
- 检查数据库查询性能
- 验证前端渲染性能
- 确认内存使用情况
- 代码质量:
- 检查代码风格
- 确保注释完整
- 验证类型定义
4. 文档更新
- 更新调试文档:
- 记录问题原因
- 描述解决方案
- 添加最佳实践
- 更新设计文档:
- 更新接口定义
- 修改数据结构
- 补充新功能说明
- 更新注释:
- 添加函数说明
- 说明参数用途
- 解释复杂逻辑
模型训练结果
从最新的训练结果来看:
- XGBoost 表现最好:
- 训练集 R² = 0.4346,没有过拟合
- 验证集 R² = 0.3625,表现最稳定
- MAE = 0.60,RMSE = 0.61,预测误差较小
- LightGBM 表现次之:
- 训练集 R² = 0.5277,轻微过拟合
- 验证集 R² = 0.1101,泛化能力一般
- MAE = 0.55,RMSE = 0.72,预测误差适中
- Random Forest:
- 训练集 R² = 0.7756,存在过拟合
- 验证集 R² = 0.3189,泛化能力还可以
- MAE = 0.47,RMSE = 0.63,预测误差较小
- GBDT 过拟合严重:
- 训练集 R² = 0.9700,严重过拟合
- 验证集 R² = -1.3133,泛化能力很差
- MAE = 0.96,RMSE = 1.17,预测误差大
建议
- 使用 XGBoost 作为主要模型
- 可以考虑集成 XGBoost 和 Random Forest
- 继续调整 LightGBM 的参数
- 暂时不使用 GBDT
数据集存在的问题
火箭炮数据集:
- Feature length_m missing rate: 0.00%
- Feature width_m missing rate: 9.09%
- Feature height_m missing rate: 9.09%
- Feature weight_kg missing rate: 0.00%
- Feature max_range_km missing rate: 45.45%
- Feature firing_angle_horizontal missing rate: 45.45%
- Feature firing_angle_vertical missing rate: 45.45%
- Feature rocket_length_m missing rate: 72.73%
- Feature rocket_diameter_mm missing rate: 0.00%
- Feature rocket_weight_kg missing rate: 72.73%
- Feature rate_of_fire missing rate: 54.55%
巡飞弹数据集:
- Feature length_m missing rate: 27.78%
- Feature width_m missing rate: 50.00%
- Feature height_m missing rate: 50.00%
- Feature weight_kg missing rate: 22.22%
- Feature max_range_km missing rate: 44.44%
- Feature wingspan_m missing rate: 50.00%
- Feature warhead_weight_kg missing rate: 77.78%
- Feature max_speed_ms missing rate: 77.78%
- Feature cruise_speed_kmh missing rate: 61.11%
- Feature flight_time_min missing rate: 33.33%