feat(app):添加单实例锁和应用拖动/退出优化

- 在 main.go 中添加了 SingleInstanceLock 配置,确保只有一个应用实例运行- 在 App 结构中添加了 OnSecondInstanceLaunch 函数,用于处理第二次启动时的通知
- 优化了应用退出流程,确保 systray 正确退出
- 调整了窗口默认大小和最小宽度
This commit is contained in:
ArvinLovegood 2025-03-21 17:53:32 +08:00
parent 98c81107fc
commit 63a05954f8
4 changed files with 63 additions and 43 deletions

45
app.go
View File

@ -14,6 +14,8 @@ import (
"github.com/duke-git/lancet/v2/strutil" "github.com/duke-git/lancet/v2/strutil"
"github.com/getlantern/systray" "github.com/getlantern/systray"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
"github.com/go-toast/toast"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/runtime" "github.com/wailsapp/wails/v2/pkg/runtime"
"go-stock/backend/data" "go-stock/backend/data"
"go-stock/backend/db" "go-stock/backend/db"
@ -118,18 +120,18 @@ func (a *App) domReady(ctx context.Context) {
} }
}() }()
go func() {
ticker := time.NewTicker(time.Second * time.Duration(60))
defer ticker.Stop()
for range ticker.C {
telegraph := refreshTelegraphList()
if telegraph != nil && config.EnableNews {
go runtime.EventsEmit(a.ctx, "telegraph", telegraph)
}
}
}()
if config.EnableNews { if config.EnableNews {
go func() {
ticker := time.NewTicker(time.Second * time.Duration(60))
defer ticker.Stop()
for range ticker.C {
telegraph := refreshTelegraphList()
if telegraph != nil {
go runtime.EventsEmit(a.ctx, "telegraph", telegraph)
}
}
}()
go runtime.EventsEmit(a.ctx, "telegraph", refreshTelegraphList()) go runtime.EventsEmit(a.ctx, "telegraph", refreshTelegraphList())
} }
go MonitorStockPrices(a) go MonitorStockPrices(a)
@ -479,6 +481,7 @@ func (a *App) shutdown(ctx context.Context) {
defer PanicHandler() defer PanicHandler()
// Perform your teardown here // Perform your teardown here
systray.Quit() systray.Quit()
os.Exit(0)
} }
// Greet returns a greeting for the given name // Greet returns a greeting for the given name
@ -673,6 +676,7 @@ func getMsgTypeName(msgType int) string {
func onExit(a *App) { func onExit(a *App) {
// 清理操作 // 清理操作
logger.SugaredLogger.Infof("onExit") logger.SugaredLogger.Infof("onExit")
systray.Quit()
runtime.Quit(a.ctx) runtime.Quit(a.ctx)
} }
@ -696,15 +700,12 @@ func onReady(a *App) {
case <-mQuitOrig.ClickedCh: case <-mQuitOrig.ClickedCh:
logger.SugaredLogger.Infof("退出应用程序") logger.SugaredLogger.Infof("退出应用程序")
runtime.Quit(a.ctx) runtime.Quit(a.ctx)
//systray.Quit()
case <-show.ClickedCh: case <-show.ClickedCh:
logger.SugaredLogger.Infof("显示应用程序") logger.SugaredLogger.Infof("显示应用程序")
runtime.WindowShow(a.ctx) runtime.WindowShow(a.ctx)
//runtime.WindowShow(a.ctx)
case <-hide.ClickedCh: case <-hide.ClickedCh:
logger.SugaredLogger.Infof("隐藏应用程序") logger.SugaredLogger.Infof("隐藏应用程序")
runtime.WindowHide(a.ctx) runtime.WindowHide(a.ctx)
} }
} }
}() }()
@ -780,3 +781,19 @@ func (a *App) FollowFund(fundCode string) string {
func (a *App) UnFollowFund(fundCode string) string { func (a *App) UnFollowFund(fundCode string) string {
return data.NewFundApi().UnFollowFund(fundCode) return data.NewFundApi().UnFollowFund(fundCode)
} }
func OnSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) {
notification := toast.Notification{
AppID: "go-stock",
Title: "go-stock",
Message: "程序已经在运行了",
Icon: "",
Duration: "short",
Audio: toast.Default,
}
err := notification.Push()
if err != nil {
logger.SugaredLogger.Error(err)
}
time.Sleep(time.Second * 3)
}

View File

@ -6,7 +6,7 @@
<title>go-stock:AI赋能股票分析</title> <title>go-stock:AI赋能股票分析</title>
<link href="./src/style.css" rel="stylesheet"> <link href="./src/style.css" rel="stylesheet">
</head> </head>
<body> <body style="--wails-draggable:drag">
<div id="app"></div> <div id="app"></div>
<script src="./src/main.js" type="module"></script> <script src="./src/main.js" type="module"></script>
</body> </body>

View File

@ -129,15 +129,15 @@ const menuOptions = ref([
key: 'hide', key: 'hide',
icon: renderIcon(ReorderTwoOutline), icon: renderIcon(ReorderTwoOutline),
}, },
{ // {
label: ()=> h("a", { // label: ()=> h("a", {
href: 'javascript:void(0)', // href: 'javascript:void(0)',
style: 'cursor: move;', // style: 'cursor: move;',
onClick: toggleStartMoveWindow, // onClick: toggleStartMoveWindow,
}, { default: () => '移动' }), // }, { default: () => '' }),
key: 'move', // key: 'move',
icon: renderIcon(MoveOutline), // icon: renderIcon(MoveOutline),
}, // },
{ {
label: ()=> h("a", { label: ()=> h("a", {
href: '#', href: '#',
@ -161,22 +161,22 @@ function toggleFullscreen(e) {
} }
isFullscreen.value=!isFullscreen.value isFullscreen.value=!isFullscreen.value
} }
const drag = ref(false) // const drag = ref(false)
const lastPos= ref({x:0,y:0}) // const lastPos= ref({x:0,y:0})
function toggleStartMoveWindow(e) { // function toggleStartMoveWindow(e) {
drag.value=!drag.value // drag.value=!drag.value
lastPos.value={x:e.clientX,y:e.clientY} // lastPos.value={x:e.clientX,y:e.clientY}
} // }
function dragstart(e) { // function dragstart(e) {
if (drag.value) { // if (drag.value) {
let x=e.clientX-lastPos.value.x // let x=e.clientX-lastPos.value.x
let y=e.clientY-lastPos.value.y // let y=e.clientY-lastPos.value.y
WindowGetPosition().then((pos) => { // WindowGetPosition().then((pos) => {
WindowSetPosition(pos.x+x,pos.y+y) // WindowSetPosition(pos.x+x,pos.y+y)
}) // })
} // }
} // }
window.addEventListener('mousemove', dragstart) // window.addEventListener('mousemove', dragstart)
EventsOn("realtime_profit",(data)=>{ EventsOn("realtime_profit",(data)=>{
realtimeProfit.value=data realtimeProfit.value=data

View File

@ -17,7 +17,6 @@ import (
"go-stock/backend/db" "go-stock/backend/db"
log "go-stock/backend/logger" log "go-stock/backend/logger"
"go-stock/backend/models" "go-stock/backend/models"
"os" "os"
goruntime "runtime" goruntime "runtime"
"runtime/debug" "runtime/debug"
@ -126,7 +125,7 @@ func main() {
width, height, err = getScreenResolution() width, height, err = getScreenResolution()
if err != nil { if err != nil {
log.SugaredLogger.Error("get screen resolution error") log.SugaredLogger.Error("get screen resolution error")
width = 1366 width = 1456
height = 768 height = 768
} }
@ -135,7 +134,7 @@ func main() {
Title: "go-stock", Title: "go-stock",
Width: width * 4 / 5, Width: width * 4 / 5,
Height: height * 4 / 5, Height: height * 4 / 5,
MinWidth: 1024, MinWidth: 1456,
MinHeight: 768, MinHeight: 768,
MaxWidth: width, MaxWidth: width,
MaxHeight: height, MaxHeight: height,
@ -156,6 +155,10 @@ func main() {
OnBeforeClose: app.beforeClose, OnBeforeClose: app.beforeClose,
OnShutdown: app.shutdown, OnShutdown: app.shutdown,
WindowStartState: options.Normal, WindowStartState: options.Normal,
SingleInstanceLock: &options.SingleInstanceLock{
UniqueId: "go-stock",
OnSecondInstanceLaunch: OnSecondInstanceLaunch,
},
Bind: []interface{}{ Bind: []interface{}{
app, app,
}, },