feat(backend): 实现股票价格实时监控功能

- 在 App 结构中添加定时更新股票价格的逻辑
- 实现 MonitorStockPrices 函数,用于更新关注股票的价格
- 在前端添加股票价格更新的事件处理
- 优化股票数据的获取和处理逻辑
This commit is contained in:
spark 2025-01-08 14:17:11 +08:00
parent e7560f3e9b
commit 1554d3309d
4 changed files with 119 additions and 18 deletions

54
app.go
View File

@ -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,

View File

@ -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
}

View File

@ -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)

View File

@ -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)