mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
feat(frontend):增加前端错误捕获和后端panic处理
- 在前端 App.vue、settings.vue 和 stock.vue 中添加 window.onerror 事件处理器,捕获前端错误并发送给后端 - 在后端 app.go 和 openai_api.go 中添加 panic 处理逻辑,捕获并记录 panic错误 - 在 main.go 中添加 PanicHandler 函数,用于捕获和处理全局 panic
This commit is contained in:
parent
22111411c3
commit
b4c55ce233
8
app.go
8
app.go
@ -41,6 +41,10 @@ func NewApp() *App {
|
|||||||
|
|
||||||
// startup is called at application startup
|
// startup is called at application startup
|
||||||
func (a *App) startup(ctx context.Context) {
|
func (a *App) startup(ctx context.Context) {
|
||||||
|
defer PanicHandler()
|
||||||
|
runtime.EventsOn(ctx, "frontendError", func(optionalData ...interface{}) {
|
||||||
|
logger.SugaredLogger.Errorf("Frontend error: %v\n", optionalData)
|
||||||
|
})
|
||||||
logger.SugaredLogger.Infof("Version:%s", Version)
|
logger.SugaredLogger.Infof("Version:%s", Version)
|
||||||
// Perform your setup here
|
// Perform your setup here
|
||||||
a.ctx = ctx
|
a.ctx = ctx
|
||||||
@ -86,6 +90,8 @@ func checkUpdate(a *App) {
|
|||||||
|
|
||||||
// domReady is called after front-end resources have been loaded
|
// domReady is called after front-end resources have been loaded
|
||||||
func (a *App) domReady(ctx context.Context) {
|
func (a *App) domReady(ctx context.Context) {
|
||||||
|
defer PanicHandler()
|
||||||
|
|
||||||
// Add your action here
|
// Add your action here
|
||||||
//定时更新数据
|
//定时更新数据
|
||||||
go func() {
|
go func() {
|
||||||
@ -321,6 +327,7 @@ func addStockFollowData(follow data.FollowedStock, stockData *data.StockInfo) {
|
|||||||
// either by clicking the window close button or calling runtime.Quit.
|
// either by clicking the window close button or calling runtime.Quit.
|
||||||
// Returning true will cause the application to continue, false will continue shutdown as normal.
|
// Returning true will cause the application to continue, false will continue shutdown as normal.
|
||||||
func (a *App) beforeClose(ctx context.Context) (prevent bool) {
|
func (a *App) beforeClose(ctx context.Context) (prevent bool) {
|
||||||
|
defer PanicHandler()
|
||||||
|
|
||||||
dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{
|
dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{
|
||||||
Type: runtime.QuestionDialog,
|
Type: runtime.QuestionDialog,
|
||||||
@ -344,6 +351,7 @@ func (a *App) beforeClose(ctx context.Context) (prevent bool) {
|
|||||||
|
|
||||||
// shutdown is called at application termination
|
// shutdown is called at application termination
|
||||||
func (a *App) shutdown(ctx context.Context) {
|
func (a *App) shutdown(ctx context.Context) {
|
||||||
|
defer PanicHandler()
|
||||||
// Perform your teardown here
|
// Perform your teardown here
|
||||||
systray.Quit()
|
systray.Quit()
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,19 @@ type AiResponse struct {
|
|||||||
|
|
||||||
func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
||||||
ch := make(chan string, 512)
|
ch := make(chan string, 512)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
logger.SugaredLogger.Error("NewChatStream panic", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
logger.SugaredLogger.Error("NewChatStream goroutine panic", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
msg := []map[string]interface{}{
|
msg := []map[string]interface{}{
|
||||||
{
|
{
|
||||||
@ -174,7 +186,7 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
|||||||
client.SetBaseURL(o.BaseUrl)
|
client.SetBaseURL(o.BaseUrl)
|
||||||
client.SetHeader("Authorization", "Bearer "+o.ApiKey)
|
client.SetHeader("Authorization", "Bearer "+o.ApiKey)
|
||||||
client.SetHeader("Content-Type", "application/json")
|
client.SetHeader("Content-Type", "application/json")
|
||||||
client.SetRetryCount(3)
|
//client.SetRetryCount(3)
|
||||||
if o.TimeOut <= 0 {
|
if o.TimeOut <= 0 {
|
||||||
o.TimeOut = 300
|
o.TimeOut = 300
|
||||||
}
|
}
|
||||||
@ -190,14 +202,15 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
|||||||
}).
|
}).
|
||||||
Post("/chat/completions")
|
Post("/chat/completions")
|
||||||
|
|
||||||
defer resp.RawBody().Close()
|
body := resp.RawBody()
|
||||||
|
defer body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.SugaredLogger.Infof("Stream error : %s", err.Error())
|
logger.SugaredLogger.Infof("Stream error : %s", err.Error())
|
||||||
ch <- err.Error()
|
ch <- err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(resp.RawBody())
|
scanner := bufio.NewScanner(body)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
logger.SugaredLogger.Infof("Received data: %s", line)
|
logger.SugaredLogger.Infof("Received data: %s", line)
|
||||||
@ -232,8 +245,13 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.SugaredLogger.Infof("Stream data error : %s", err.Error())
|
if err != nil {
|
||||||
ch <- err.Error()
|
logger.SugaredLogger.Infof("Stream data error : %s", err.Error())
|
||||||
|
ch <- err.Error()
|
||||||
|
} else {
|
||||||
|
logger.SugaredLogger.Infof("Stream data error : %s", data)
|
||||||
|
ch <- data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ch <- line
|
ch <- line
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import stockInfo from './components/stock.vue'
|
import stockInfo from './components/stock.vue'
|
||||||
import {
|
import {
|
||||||
|
EventsEmit,
|
||||||
EventsOn,
|
EventsOn,
|
||||||
Quit,
|
Quit,
|
||||||
WindowFullscreen, WindowGetPosition,
|
WindowFullscreen, WindowGetPosition,
|
||||||
@ -157,6 +158,18 @@ EventsOn("realtime_profit",(data)=>{
|
|||||||
EventsOn("telegraph",(data)=>{
|
EventsOn("telegraph",(data)=>{
|
||||||
telegraph.value=data
|
telegraph.value=data
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.onerror = function (message, source, lineno, colno, error) {
|
||||||
|
// 将错误信息发送给后端
|
||||||
|
EventsEmit("frontendError", {
|
||||||
|
message: message,
|
||||||
|
source: source,
|
||||||
|
lineno: lineno,
|
||||||
|
colno: colno,
|
||||||
|
error: error ? error.stack : null
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import {onMounted, ref, watch} from "vue";
|
|||||||
import {ExportConfig, GetConfig, SendDingDingMessageByType, UpdateConfig} from "../../wailsjs/go/main/App";
|
import {ExportConfig, GetConfig, SendDingDingMessageByType, UpdateConfig} from "../../wailsjs/go/main/App";
|
||||||
import {useMessage} from "naive-ui";
|
import {useMessage} from "naive-ui";
|
||||||
import {data} from "../../wailsjs/go/models";
|
import {data} from "../../wailsjs/go/models";
|
||||||
|
import {EventsEmit} from "../../wailsjs/runtime";
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
@ -150,6 +151,19 @@ function importConfig(){
|
|||||||
};
|
};
|
||||||
input.click();
|
input.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
window.onerror = function (message, source, lineno, colno, error) {
|
||||||
|
// 将错误信息发送给后端
|
||||||
|
EventsEmit("frontendError", {
|
||||||
|
message: message,
|
||||||
|
source: source,
|
||||||
|
lineno: lineno,
|
||||||
|
colno: colno,
|
||||||
|
error: error ? error.stack : null
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
useModal,
|
useModal,
|
||||||
useNotification
|
useNotification
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import {EventsOn, WindowFullscreen, WindowReload, WindowUnfullscreen} from '../../wailsjs/runtime'
|
import {EventsEmit, EventsOn, WindowFullscreen, WindowReload, WindowUnfullscreen} from '../../wailsjs/runtime'
|
||||||
import {Add, Search,StarOutline} from '@vicons/ionicons5'
|
import {Add, Search,StarOutline} from '@vicons/ionicons5'
|
||||||
import { MdPreview } from 'md-editor-v3';
|
import { MdPreview } from 'md-editor-v3';
|
||||||
// preview.css相比style.css少了编辑器那部分样式
|
// preview.css相比style.css少了编辑器那部分样式
|
||||||
@ -546,7 +546,17 @@ function getHeight() {
|
|||||||
return document.documentElement.clientHeight
|
return document.documentElement.clientHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.onerror = function (message, source, lineno, colno, error) {
|
||||||
|
// 将错误信息发送给后端
|
||||||
|
EventsEmit("frontendError", {
|
||||||
|
message: message,
|
||||||
|
source: source,
|
||||||
|
lineno: lineno,
|
||||||
|
colno: colno,
|
||||||
|
error: error ? error.stack : null
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
10
main.go
10
main.go
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
"github.com/wailsapp/wails/v2"
|
"github.com/wailsapp/wails/v2"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
@ -18,6 +19,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -206,3 +208,11 @@ func checkDir(dir string) {
|
|||||||
logger.NewDefaultLogger().Info("create dir: " + dir)
|
logger.NewDefaultLogger().Info("create dir: " + dir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PanicHandler 捕获 panic 的包装函数
|
||||||
|
func PanicHandler() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Printf("Recovered from panic: %v\n", r)
|
||||||
|
debug.PrintStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user