feat: 添加配置导入功能
将重置参数按钮改为导入配置按钮,并实现TOML文件解析和参数导入功能
This commit is contained in:
@@ -267,11 +267,11 @@
|
||||
class="px-8"
|
||||
/>
|
||||
<q-btn
|
||||
color="grey-7"
|
||||
color="orange"
|
||||
size="lg"
|
||||
label="重置参数"
|
||||
icon="refresh"
|
||||
@click="resetParams"
|
||||
label="导入配置"
|
||||
icon="upload"
|
||||
@click="importConfig"
|
||||
class="px-8"
|
||||
/>
|
||||
<q-btn
|
||||
@@ -284,6 +284,15 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 隐藏的文件输入 -->
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept=".toml"
|
||||
style="display: none"
|
||||
@change="handleFileSelect"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<!-- 错误信息 -->
|
||||
@@ -355,6 +364,7 @@ const calculating = ref(false)
|
||||
const result = ref<string | null>(null)
|
||||
const error = ref<string | null>(null)
|
||||
const logRef = ref<InstanceType<typeof LogComponent> | null>(null)
|
||||
const fileInput = ref<HTMLInputElement | null>(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 {
|
||||
|
||||
Reference in New Issue
Block a user