diff --git a/webui/src/components/ParameterForm.vue b/webui/src/components/ParameterForm.vue index d03f5da..2e0ec8e 100644 --- a/webui/src/components/ParameterForm.vue +++ b/webui/src/components/ParameterForm.vue @@ -2,16 +2,20 @@ - +
EGM 输电线路绕击跳闸率计算
+
+ {{ currentFilePath }} +
+
@@ -342,7 +346,7 @@ />
- + (null) const logRef = ref | null>(null) const animationRef = ref | null>(null) const fileInput = ref(null) +// 当前打开的文件路径 +const currentFilePath = ref('') // 雷电流概率密度系数设置开关 const showIpCoefficients = ref(false) // 50%击穿电压设置开关 @@ -582,6 +588,16 @@ const calculate = async () => { } } + // 验证50%击穿电压 + if (showU50.value) { + const u50 = Number(params.advance.u_50) + if (u50 < 1000) { + error.value = '请检查参数:"50%击穿电压 U_50"的值应该大于等于 1000 kV' + logRef.value?.addLog('error', '请检查参数:"50%击穿电压 U_50"的值应该大于等于 1000 kV') + return + } + } + calculating.value = true result.value = null error.value = null @@ -771,12 +787,44 @@ const exportConfig = async () => { } } -// 导入配置 - 触发文件选择 -const importConfig = () => { - fileInput.value?.click() +// 导入配置 - 调用后端文件对话框 +const importConfig = async () => { + try { + if (window.pywebview) { + const response = await window.pywebview.api.import_config() + if (response.success && response.params) { + // 合并导入的参数到当前参数 + if (response.params.parameter) { + Object.assign(params.parameter, response.params.parameter) + } + if (response.params.advance) { + Object.assign(params.advance, response.params.advance) + } + if (response.params.optional) { + Object.assign(params.optional, response.params.optional) + } + + // 显示完整文件路径 + currentFilePath.value = response.file_path || '' + + logRef.value?.addLog('info', `成功导入配置: ${response.file_path}`) + result.value = null + error.value = null + } else if (!response.success && response.message !== '用户取消了选择') { + error.value = response.message || '导入失败' + logRef.value?.addLog('error', response.message || '导入失败') + } + } else { + // 开发模式下使用 HTML 文件输入 + fileInput.value?.click() + } + } catch (e: any) { + error.value = e.message || '导入失败' + logRef.value?.addLog('error', e.message || '导入失败') + } } -// 处理文件选择 +// 处理文件选择(开发模式备用) const handleFileSelect = async (event: Event) => { const input = event.target as HTMLInputElement const file = input.files?.[0] @@ -797,6 +845,8 @@ const handleFileSelect = async (event: Event) => { Object.assign(params.optional, importedParams.optional) } + currentFilePath.value = file.name + logRef.value?.addLog('info', `成功导入配置: ${file.name}`) result.value = null error.value = null @@ -815,6 +865,7 @@ declare global { pywebview?: { api: { calculate: (params: AllParameters) => Promise + import_config: () => Promise export_config: (params: AllParameters) => Promise export_log: (logText: string) => Promise } diff --git a/webview_app.py b/webview_app.py index d719bd4..30754fd 100644 --- a/webview_app.py +++ b/webview_app.py @@ -9,6 +9,7 @@ import json import math import threading import queue +import tomllib from pathlib import Path from typing import Dict, Any, List from datetime import datetime @@ -524,6 +525,46 @@ class EGMWebApp: "message": f"保存失败: {str(e)}" } + def import_config(self) -> Dict[str, Any]: + """ + 导入配置从 TOML 文件,弹出打开对话框 + + Returns: + 包含解析后的参数和文件路径的字典 + """ + try: + # 打开文件选择对话框 + result = self.window.create_file_dialog( + webview.OPEN_DIALOG, + directory='', + file_types=('TOML Files (*.toml)', 'All files (*.*)') + ) + + if result and len(result) > 0: + file_path = result[0] + + # 读取并解析 TOML 文件 + with open(file_path, 'rb') as f: + toml_data = tomllib.load(f) + + return { + "success": True, + "message": f"成功导入配置", + "file_path": file_path, + "params": toml_data + } + else: + return { + "success": False, + "message": "用户取消了选择" + } + except Exception as e: + logger.error(f"导入配置失败: {str(e)}") + return { + "success": False, + "message": f"导入失败: {str(e)}" + } + def get_default_config(self) -> Dict[str, Any]: """ 获取默认配置