From 1554d3309dbe32be18def8a874aee24e12d76faf Mon Sep 17 00:00:00 2001 From: spark Date: Wed, 8 Jan 2025 14:17:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(backend):=20=E5=AE=9E=E7=8E=B0=E8=82=A1?= =?UTF-8?q?=E7=A5=A8=E4=BB=B7=E6=A0=BC=E5=AE=9E=E6=97=B6=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 App 结构中添加定时更新股票价格的逻辑 - 实现 MonitorStockPrices 函数,用于更新关注股票的价格 - 在前端添加股票价格更新的事件处理 - 优化股票数据的获取和处理逻辑 --- app.go | 54 +++++++++++++++++++++++----- backend/data/stock_data_api.go | 14 ++++---- frontend/src/components/stock.vue | 60 ++++++++++++++++++++++++++++++- main.go | 9 +++-- 4 files changed, 119 insertions(+), 18 deletions(-) diff --git a/app.go b/app.go index 8cfdbb6..8577d06 100644 --- a/app.go +++ b/app.go @@ -12,6 +12,7 @@ import ( "go-stock/backend/data" "go-stock/backend/db" "go-stock/backend/logger" + "time" ) // App struct @@ -46,14 +47,51 @@ func (a *App) startup(ctx context.Context) { // domReady is called after front-end resources have been loaded func (a *App) domReady(ctx context.Context) { // Add your action here - //ticker := time.NewTicker(time.Second) - //defer ticker.Stop() - ////定时更新数据 - //go func() { - // for range ticker.C { - // runtime.WindowSetTitle(ctx, "go-stock "+time.Now().Format("2006-01-02 15:04:05")) - // } - //}() + + //定时更新数据 + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for range ticker.C { + runtime.WindowSetTitle(ctx, "go-stock "+time.Now().Format("2006-01-02 15:04:05")) + } + }() + + //定时更新数据 + go func() { + ticker := time.NewTicker(time.Second * 2) + defer ticker.Stop() + for range ticker.C { + MonitorStockPrices(a) + } + }() +} +func MonitorStockPrices(a *App) { + dest := &[]data.FollowedStock{} + db.Dao.Model(&data.FollowedStock{}).Find(dest) + for _, item := range *dest { + follow := item + stockCode := follow.StockCode + go func() { + stockData, err := data.NewStockDataApi().GetStockCodeRealTimeData(stockCode) + if err != nil { + logger.SugaredLogger.Errorf("get stock code real time data error:%s", err.Error()) + return + } + + price, err := convertor.ToFloat(stockData.Price) + if err != nil { + return + } + if follow.Price != price { + runtime.EventsEmit(a.ctx, "stock_price", stockData) + go db.Dao.Model(follow).Where("stock_code = ?", stockCode).Updates(map[string]interface{}{ + "price": stockData.Price, + }) + } + + }() + } } // beforeClose is called when the application is about to quit, diff --git a/backend/data/stock_data_api.go b/backend/data/stock_data_api.go index 2667e4b..af809ec 100644 --- a/backend/data/stock_data_api.go +++ b/backend/data/stock_data_api.go @@ -268,13 +268,13 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCode string) (*StockI return &StockInfo{}, nil } stockData, err := ParseFullSingleStockData(GB18030ToUTF8(resp.Body())) - var count int64 - db.Dao.Model(&StockInfo{}).Where("code = ?", StockCode).Count(&count) - if count == 0 { - go db.Dao.Model(&StockInfo{}).Create(stockData) - } else { - go db.Dao.Model(&StockInfo{}).Where("code = ?", StockCode).Updates(stockData) - } + //var count int64 + //db.Dao.Model(&StockInfo{}).Where("code = ?", StockCode).Count(&count) + //if count == 0 { + // go db.Dao.Model(&StockInfo{}).Create(stockData) + //} else { + // go db.Dao.Model(&StockInfo{}).Where("code = ?", StockCode).Updates(stockData) + //} return stockData, err } diff --git a/frontend/src/components/stock.vue b/frontend/src/components/stock.vue index 3e0e3eb..fda15e3 100644 --- a/frontend/src/components/stock.vue +++ b/frontend/src/components/stock.vue @@ -84,7 +84,7 @@ onMounted(() => { ticker.value=setInterval(() => { if(isTradingTime()){ - monitor() + //monitor() data.fenshiURL='http://image.sinajs.cn/newchart/min/n/'+data.code+'.gif'+"?t="+Date.now() } }, 3500) @@ -103,6 +103,10 @@ EventsOn("showSearch",(data)=>{ addBTN.value = data === 1; }) +EventsOn("stock_price",(data)=>{ + console.log("stock_price",data['股票代码']) + updateData(data) +}) EventsOn("refreshFollowList",(data)=>{ @@ -183,6 +187,60 @@ function getStockList(value){ } } +async function updateData(result) { + if(result["当前价格"]<=0){ + result["当前价格"]=result["卖一报价"] + } + + let s=(result["当前价格"]-result["昨日收盘价"])*100/result["昨日收盘价"] + let roundedNum = s.toFixed(2); // 将数字转换为保留两位小数的字符串形式 + result.s=roundedNum+"%" + + result.highRate=((result["今日最高价"]-result["今日开盘价"])*100/result["今日开盘价"]).toFixed(2)+"%" + result.lowRate=((result["今日最低价"]-result["今日开盘价"])*100/result["今日开盘价"]).toFixed(2)+"%" + + if (roundedNum>0) { + result.type="error" + result.color="#E88080" + }else if (roundedNum<0) { + result.type="success" + result.color="#63E2B7" + }else { + result.type="default" + result.color="#FFFFFF" + } + let res= followList.value.filter(item => item.StockCode===result['股票代码']) + if (res.length>0) { + result.Sort=res[0].Sort + result.costPrice=res[0].CostPrice + result.volume=res[0].Volume + result.profit=((result["当前价格"]-result.costPrice)*100/result.costPrice).toFixed(3) + result.profitAmountToday=(result.volume*(result["当前价格"]-result["昨日收盘价"])).toFixed(2) + result.profitAmount=(result.volume*(result["当前价格"]-result.costPrice)).toFixed(2) + if(result.profitAmount>0){ + result.profitType="error" + }else if(result.profitAmount<0){ + result.profitType="success" + } + if(result["当前价格"]){ + if(res[0].AlarmChangePercent>0&&Math.abs(roundedNum)>=res[0].AlarmChangePercent){ + SendMessage(result,1) + } + + if(res[0].AlarmPrice>0&&result["当前价格"]>=res[0].AlarmPrice){ + SendMessage(result,2) + } + + if(res[0].CostPrice>0&&result["当前价格"]>=res[0].CostPrice){ + SendMessage(result,3) + } + } + } + result.key=GetSortKey(result.Sort,result["股票代码"]) + results.value[GetSortKey(result.Sort,result["股票代码"])]=result +} + + async function monitor() { for (let code of stocks.value) { // console.log(code) diff --git a/main.go b/main.go index 28d83c3..59cfc93 100644 --- a/main.go +++ b/main.go @@ -44,8 +44,7 @@ func main() { if stocksBin != nil && len(stocksBin) > 0 { go initStockData() } - go data.NewStockDataApi().GetStockBaseInfo() - go data.NewStockDataApi().GetIndexBasic() + //updateBasicInfo() // Create an instance of the app structure app := NewApp() @@ -141,6 +140,12 @@ func main() { } +func updateBasicInfo() { + //更新基本信息 + go data.NewStockDataApi().GetStockBaseInfo() + go data.NewStockDataApi().GetIndexBasic() +} + func initStockData() { var count int64 db.Dao.Model(&data.StockBasic{}).Count(&count)