feat: 添加配置文件的导入功能及文件路径显示

新增通过系统对话框导入配置文件的功能
在界面上显示当前打开的配置文件路径
添加对50%击穿电压的验证
优化开发模式下的文件导入备用方案
This commit is contained in:
dmy
2026-03-03 18:58:19 +08:00
parent 7dd466a28a
commit 86b294baf9
2 changed files with 98 additions and 6 deletions

View File

@@ -2,16 +2,20 @@
<q-layout view="lHh lpr lFf"> <q-layout view="lHh lpr lFf">
<q-header elevated class="bg-indigo-600 text-white"> <q-header elevated class="bg-indigo-600 text-white">
<q-toolbar> <q-toolbar>
<q-toolbar-title> <q-toolbar-title class="q-py-sm">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<q-icon name="flash_on" size="md" /> <q-icon name="flash_on" size="md" />
<span class="text-xl font-bold">EGM 输电线路绕击跳闸率计算</span> <span class="text-xl font-bold">EGM 输电线路绕击跳闸率计算</span>
</div> </div>
<div v-if="currentFilePath" class="text-sm truncate max-w-2xl bg-white text-green-700 px-2 py-0.5 rounded mt-1" :title="currentFilePath">
{{ currentFilePath }}
</div>
</q-toolbar-title> </q-toolbar-title>
</q-toolbar> </q-toolbar>
</q-header> </q-header>
<q-page-container> <q-page-container>
<q-page class="q-pa-md"> <q-page class="q-pa-md">
<div class="max-w-4xl mx-auto"> <div class="max-w-4xl mx-auto">
<!-- 基本参数 --> <!-- 基本参数 -->
@@ -342,7 +346,7 @@
/> />
</div> </div>
<!-- 隐藏的文件输入 --> <!-- 隐藏的文件输入开发模式备用 -->
<input <input
ref="fileInput" ref="fileInput"
type="file" type="file"
@@ -441,6 +445,8 @@ const error = ref<string | null>(null)
const logRef = ref<InstanceType<typeof LogComponent> | null>(null) const logRef = ref<InstanceType<typeof LogComponent> | null>(null)
const animationRef = ref<InstanceType<typeof Animation> | null>(null) const animationRef = ref<InstanceType<typeof Animation> | null>(null)
const fileInput = ref<HTMLInputElement | null>(null) const fileInput = ref<HTMLInputElement | null>(null)
// 当前打开的文件路径
const currentFilePath = ref<string>('')
// 雷电流概率密度系数设置开关 // 雷电流概率密度系数设置开关
const showIpCoefficients = ref(false) const showIpCoefficients = ref(false)
// 50%击穿电压设置开关 // 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 calculating.value = true
result.value = null result.value = null
error.value = null error.value = null
@@ -771,12 +787,44 @@ const exportConfig = async () => {
} }
} }
// 导入配置 - 触发文件选择 // 导入配置 - 调用后端文件对话框
const importConfig = () => { 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() fileInput.value?.click()
}
} catch (e: any) {
error.value = e.message || '导入失败'
logRef.value?.addLog('error', e.message || '导入失败')
}
} }
// 处理文件选择 // 处理文件选择(开发模式备用)
const handleFileSelect = async (event: Event) => { const handleFileSelect = async (event: Event) => {
const input = event.target as HTMLInputElement const input = event.target as HTMLInputElement
const file = input.files?.[0] const file = input.files?.[0]
@@ -797,6 +845,8 @@ const handleFileSelect = async (event: Event) => {
Object.assign(params.optional, importedParams.optional) Object.assign(params.optional, importedParams.optional)
} }
currentFilePath.value = file.name
logRef.value?.addLog('info', `成功导入配置: ${file.name}`) logRef.value?.addLog('info', `成功导入配置: ${file.name}`)
result.value = null result.value = null
error.value = null error.value = null
@@ -815,6 +865,7 @@ declare global {
pywebview?: { pywebview?: {
api: { api: {
calculate: (params: AllParameters) => Promise<any> calculate: (params: AllParameters) => Promise<any>
import_config: () => Promise<any>
export_config: (params: AllParameters) => Promise<any> export_config: (params: AllParameters) => Promise<any>
export_log: (logText: string) => Promise<any> export_log: (logText: string) => Promise<any>
} }

View File

@@ -9,6 +9,7 @@ import json
import math import math
import threading import threading
import queue import queue
import tomllib
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List from typing import Dict, Any, List
from datetime import datetime from datetime import datetime
@@ -524,6 +525,46 @@ class EGMWebApp:
"message": f"保存失败: {str(e)}" "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]: def get_default_config(self) -> Dict[str, Any]:
""" """
获取默认配置 获取默认配置