feat(core): 用 cron 替代 ticker 实现定时任务

- 使用 cron 库替换原有的 ticker 实现,提高定时任务的准确性和灵活性
- 新增 cronEntrys 字典用于管理定时任务,便于更新和删除
- 修改数据刷新间隔的设置方式,支持动态更新
- 优化股票监控和新闻刷新的定时任务执行逻辑
This commit is contained in:
ArvinLovegood 2025-04-01 16:07:55 +08:00
parent 63e898bef8
commit 5096bfac68
4 changed files with 76 additions and 29 deletions

69
app.go
View File

@ -115,34 +115,66 @@ func (a *App) domReady(ctx context.Context) {
if interval <= 0 {
interval = 1
}
ticker := time.NewTicker(time.Second * time.Duration(interval))
defer ticker.Stop()
for range ticker.C {
//ticker := time.NewTicker(time.Second * time.Duration(interval))
//defer ticker.Stop()
//for range ticker.C {
// MonitorStockPrices(a)
//}
id, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval), func() {
MonitorStockPrices(a)
})
if err != nil {
logger.SugaredLogger.Errorf("AddFunc error:%s", err.Error())
} else {
a.cronEntrys["MonitorStockPrices"] = id
}
}()
//刷新基金净值信息
go func() {
ticker := time.NewTicker(time.Second * time.Duration(60))
defer ticker.Stop()
for range ticker.C {
//ticker := time.NewTicker(time.Second * time.Duration(60))
//defer ticker.Stop()
//for range ticker.C {
// MonitorFundPrices(a)
//}
id, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", 60), func() {
MonitorFundPrices(a)
})
if err != nil {
logger.SugaredLogger.Errorf("AddFunc error:%s", err.Error())
} else {
a.cronEntrys["MonitorFundPrices"] = id
}
}()
if config.EnableNews {
go func() {
ticker := time.NewTicker(time.Second * time.Duration(60))
defer ticker.Stop()
for range ticker.C {
//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)
// }
// }
//
//}()
id, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", 60), func() {
telegraph := refreshTelegraphList()
if telegraph != nil {
go runtime.EventsEmit(a.ctx, "telegraph", telegraph)
}
})
if err != nil {
logger.SugaredLogger.Errorf("AddFunc error:%s", err.Error())
} else {
a.cronEntrys["refreshTelegraphList"] = id
}
}()
go runtime.EventsEmit(a.ctx, "telegraph", refreshTelegraphList())
}
go MonitorStockPrices(a)
@ -779,6 +811,17 @@ func onReady(a *App) {
func (a *App) UpdateConfig(settings *data.Settings) string {
//logger.SugaredLogger.Infof("UpdateConfig:%+v", settings)
if settings.RefreshInterval > 0 {
if entryID, exists := a.cronEntrys["MonitorStockPrices"]; exists {
a.cron.Remove(entryID)
}
id, _ := a.cron.AddFunc(fmt.Sprintf("@every %ds", settings.RefreshInterval), func() {
logger.SugaredLogger.Infof("MonitorStockPrices:%s", time.Now())
MonitorStockPrices(a)
})
a.cronEntrys["MonitorStockPrices"] = id
}
return data.NewSettingsApi(settings).UpdateConfig()
}
@ -896,7 +939,9 @@ func (a *App) SetStockAICron(cronText, stockCode string) {
a.cron.Remove(entryID)
}
follow := data.NewStockDataApi().GetFollowedStockByStockCode(stockCode)
a.cron.AddFunc(cronText, a.AddCronTask(follow))
id, _ := a.cron.AddFunc(cronText, a.AddCronTask(follow))
a.cronEntrys[stockCode] = id
}
func OnSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) {
notification := toast.Notification{

View File

@ -412,11 +412,13 @@ func (receiver StockDataApi) SetAlarmChangePercent(val, alarmPrice float64, stoc
func (receiver StockDataApi) SetStockSort(sort int64, stockCode string) {
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
stockCode = strings.ToUpper(stockCode)
stockCode = strings.ToLower(stockCode)
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
stockCode = strings.Replace(stockCode, "GB_", "us", 1)
}
db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", strings.ToLower(stockCode)).Update("sort", sort)
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", strings.ToLower(stockCode)).Update("sort", sort).Error
if err != nil {
logger.SugaredLogger.Error(err.Error())
}
}
func (receiver StockDataApi) SetStockAICron(cron string, stockCode string) {
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {

View File

@ -266,7 +266,7 @@ function deletePrompt(ID){
<n-form-item-gi :span="4" label="启动时更新A股/指数信息:" path="updateBasicInfoOnStart" >
<n-switch v-model:value="formValue.updateBasicInfoOnStart" />
</n-form-item-gi>
<n-form-item-gi :span="5" label="数据刷新间隔(重启生效)" path="refreshInterval" >
<n-form-item-gi :span="5" label="数据刷新间隔" path="refreshInterval" >
<n-input-number v-model:value="formValue.refreshInterval" placeholder="请输入数据刷新间隔(秒)">
<template #suffix>

View File

@ -46,7 +46,7 @@ import html2canvas from "html2canvas";
import {asBlob} from 'html-docx-js-typescript';
import vueDanmaku from 'vue3-danmaku'
import {keys, pad} from "lodash";
import {keys, pad, padStart} from "lodash";
const danmus = ref([])
const ws = ref(null)
@ -118,7 +118,7 @@ const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/maste
const sortedResults = computed(() => {
//console.log("computed",sortedResults.value)
const sortedKeys =keys(results.value).sort();
//console.log("sortedKeys",sortedKeys)
console.log("sortedKeys",sortedKeys)
const sortedObject = {};
sortedKeys.forEach(key => {
sortedObject[key] = results.value[key];
@ -494,8 +494,8 @@ async function updateData(result) {
}
}
result.key=result.sort
//result.key=GetSortKey(result.sort,result[""])
//result.key=result.sort
result.key=GetSortKey(result.sort,result["股票代码"])
results.value[GetSortKey(result.sort,result["股票代码"])]=result
}
@ -511,9 +511,9 @@ async function monitor() {
function GetSortKey(sort,code){
//let sortKey= pad(sort,6,'0')+"_"+code
//console.log("GetSortKey:",sortKey)
return sort
let sortKey= padStart(sort,8,'0')+"_"+code
console.log("GetSortKey:",sortKey)
return sortKey
}
function onSelect(item) {
@ -865,7 +865,7 @@ function share(code,name){
</vue-danmaku>
<n-grid :x-gap="8" :cols="3" :y-gap="8" >
<n-gi :id="result['股票代码']+'_gi'" v-for="result in sortedResults" style="margin-left: 2px;" >
<n-card :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true" :title="result['股票名称']" :closable="false" @close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
<n-card :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true" :title="result['股票名称']+'_'+result.sort" :closable="false" @close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
<n-grid :cols="1" :y-gap="6">
<n-gi>
<n-text :type="result.type" >