feat: 添加日志导出功能
This commit is contained in:
@@ -67,11 +67,17 @@ const clearLog = () => {
|
||||
logs.value = []
|
||||
}
|
||||
|
||||
// 获取日志文本
|
||||
const getLogsText = (): string => {
|
||||
return logs.value.map(log => `[${log.time}] [${log.level.toUpperCase()}] ${log.message}`).join('\n')
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
addLog,
|
||||
clearLog,
|
||||
lastTripRates
|
||||
lastTripRates,
|
||||
getLogsText
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -287,6 +287,14 @@
|
||||
@click="exportConfig"
|
||||
class="px-8"
|
||||
/>
|
||||
<q-btn
|
||||
color="grey"
|
||||
size="lg"
|
||||
label="导出日志"
|
||||
icon="description"
|
||||
@click="exportLog"
|
||||
class="px-8"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 隐藏的文件输入 -->
|
||||
@@ -585,6 +593,40 @@ const parseToml = (tomlStr: string): any => {
|
||||
return result
|
||||
}
|
||||
|
||||
// 导出日志
|
||||
const exportLog = async () => {
|
||||
try {
|
||||
const logText = logRef.value?.getLogsText() || ''
|
||||
if (!logText) {
|
||||
logRef.value?.addLog('warning', '暂无日志可导出')
|
||||
return
|
||||
}
|
||||
|
||||
if (window.pywebview) {
|
||||
const response = await window.pywebview.api.export_log(logText)
|
||||
if (response.success) {
|
||||
logRef.value?.addLog('info', response.message)
|
||||
} else {
|
||||
logRef.value?.addLog('warning', response.message)
|
||||
}
|
||||
} else {
|
||||
// 开发模式下的模拟
|
||||
logRef.value?.addLog('info', '导出日志(开发模式,直接下载)')
|
||||
const blob = new Blob([logText], { type: 'text/plain' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:-]/g, '')
|
||||
a.download = `egm_log_${timestamp}.txt`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
} catch (e: any) {
|
||||
error.value = e.message || '导出日志失败'
|
||||
logRef.value?.addLog('error', e.message || '导出日志失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 导出配置
|
||||
const exportConfig = async () => {
|
||||
try {
|
||||
@@ -659,6 +701,7 @@ declare global {
|
||||
api: {
|
||||
calculate: (params: AllParameters) => Promise<any>
|
||||
export_config: (params: AllParameters) => Promise<any>
|
||||
export_log: (logText: string) => Promise<any>
|
||||
}
|
||||
}
|
||||
addLogFromBackend?: (log: { level: string; time: string; message: string }) => void
|
||||
|
||||
@@ -348,6 +348,53 @@ class EGMWebApp:
|
||||
"message": f"保存失败: {str(e)}"
|
||||
}
|
||||
|
||||
def export_log(self, log_text: str) -> Dict[str, Any]:
|
||||
"""
|
||||
导出日志为 TXT 文件,弹出保存对话框
|
||||
|
||||
Args:
|
||||
log_text: 日志文本内容
|
||||
|
||||
Returns:
|
||||
包含保存状态和路径的字典
|
||||
"""
|
||||
try:
|
||||
# 生成默认文件名
|
||||
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
default_filename = f'egm_log_{timestamp}.txt'
|
||||
|
||||
# 打开保存文件对话框
|
||||
result = self.window.create_file_dialog(
|
||||
webview.SAVE_DIALOG,
|
||||
directory='',
|
||||
save_filename=default_filename,
|
||||
file_types=('Text Files (*.txt)', 'All files (*.*)')
|
||||
)
|
||||
|
||||
if result and len(result) > 0:
|
||||
file_path = result[0]
|
||||
|
||||
# 写入文件
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(log_text)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"日志已保存到: {file_path}",
|
||||
"file_path": file_path
|
||||
}
|
||||
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]:
|
||||
"""
|
||||
获取默认配置
|
||||
|
||||
Reference in New Issue
Block a user