diff --git a/webui/src/components/ParameterForm.vue b/webui/src/components/ParameterForm.vue
index 58842b5..8d1f76d 100644
--- a/webui/src/components/ParameterForm.vue
+++ b/webui/src/components/ParameterForm.vue
@@ -267,11 +267,11 @@
class="px-8"
/>
+
+
+
@@ -355,6 +364,7 @@ const calculating = ref(false)
const result = ref(null)
const error = ref(null)
const logRef = ref | null>(null)
+const fileInput = ref(null)
const voltageOptions = [
'110kV', '220kV', '330kV', '500kV', '750kV','1000kV',
@@ -440,13 +450,6 @@ const calculate = async () => {
}
}
-// 重置参数
-const resetParams = () => {
- Object.assign(params, JSON.parse(JSON.stringify(defaultParams)))
- result.value = null
- error.value = null
-}
-
// 将参数转换为 TOML 格式
const tomlStringify = (obj: any, indent: string = ''): string => {
let result = ''
@@ -471,6 +474,72 @@ const tomlStringify = (obj: any, indent: string = ''): string => {
return result
}
+// 解析 TOML 格式字符串
+const parseToml = (tomlStr: string): any => {
+ const result: any = {}
+ let currentSection: any = result
+ let currentSectionName = ''
+
+ const lines = tomlStr.split('\n')
+
+ for (let line of lines) {
+ line = line.trim()
+
+ // 跳过空行和注释
+ if (!line || line.startsWith('#')) continue
+
+ // 匹配 section [xxx]
+ const sectionMatch = line.match(/^\[([^\]]+)\]$/)
+ if (sectionMatch) {
+ currentSectionName = sectionMatch[1]
+ currentSection = {}
+ result[currentSectionName] = currentSection
+ continue
+ }
+
+ // 匹配 key = value
+ const kvMatch = line.match(/^([^=]+)=(.*)$/)
+ if (kvMatch) {
+ const key = kvMatch[1].trim()
+ let value: any = kvMatch[2].trim()
+
+ // 解析数组 [1, 2, 3]
+ if (value.startsWith('[') && value.endsWith(']')) {
+ const arrStr = value.slice(1, -1).trim()
+ if (arrStr) {
+ value = arrStr.split(',').map((s: string) => {
+ s = s.trim()
+ if (s.startsWith('"') && s.endsWith('"')) {
+ return s.slice(1, -1)
+ }
+ return isNaN(Number(s)) ? s : Number(s)
+ })
+ } else {
+ value = []
+ }
+ }
+ // 解析字符串 "xxx"
+ else if (value.startsWith('"') && value.endsWith('"')) {
+ value = value.slice(1, -1)
+ }
+ // 解析布尔值
+ else if (value === 'true') {
+ value = true
+ } else if (value === 'false') {
+ value = false
+ }
+ // 解析数字
+ else if (!isNaN(Number(value))) {
+ value = Number(value)
+ }
+
+ currentSection[key] = value
+ }
+ }
+
+ return result
+}
+
// 导出配置
const exportConfig = async () => {
try {
@@ -500,6 +569,44 @@ const exportConfig = async () => {
}
}
+// 导入配置 - 触发文件选择
+const importConfig = () => {
+ fileInput.value?.click()
+}
+
+// 处理文件选择
+const handleFileSelect = async (event: Event) => {
+ const input = event.target as HTMLInputElement
+ const file = input.files?.[0]
+ if (!file) return
+
+ try {
+ const content = await file.text()
+ const importedParams = parseToml(content)
+
+ // 合并导入的参数到当前参数
+ if (importedParams.parameter) {
+ Object.assign(params.parameter, importedParams.parameter)
+ }
+ if (importedParams.advance) {
+ Object.assign(params.advance, importedParams.advance)
+ }
+ if (importedParams.optional) {
+ Object.assign(params.optional, importedParams.optional)
+ }
+
+ logRef.value?.addLog('info', `成功导入配置: ${file.name}`)
+ result.value = null
+ error.value = null
+ } catch (e: any) {
+ error.value = e.message || '导入失败'
+ logRef.value?.addLog('error', e.message || '导入失败')
+ }
+
+ // 清空 input 以便可以重复选择同一个文件
+ input.value = ''
+}
+
// 声明 pywebview API 类型
declare global {
interface Window {