From 9dc8fa97df97e232efc7151f32f7bf385a9e1ebd Mon Sep 17 00:00:00 2001 From: sparkmemory Date: Sat, 11 Jan 2025 14:16:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(settings):=20=E6=B7=BB=E5=8A=A0=E6=8E=A8?= =?UTF-8?q?=E9=80=81=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=9C=AC=E5=9C=B0=E6=8E=A8=E9=80=81=E5=92=8C=E9=92=89?= =?UTF-8?q?=E9=92=89=E6=8E=A8=E9=80=81=E7=9A=84=E9=85=8D=E7=BD=AE=E9=80=89?= =?UTF-8?q?=E9=A1=B9=20-=20=E5=AE=9E=E7=8E=B0=E9=85=8D=E7=BD=AE=E7=9A=84?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=92=8C=E8=AF=BB=E5=8F=96=E5=8A=9F=E8=83=BD?= =?UTF-8?q?-=20=E6=B7=BB=E5=8A=A0=E6=B5=8B=E8=AF=95=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E6=8C=89=E9=92=AE=20-=E4=BC=98=E5=8C=96=E8=82=A1=E7=A5=A8?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E7=9A=84=E6=98=BE=E7=A4=BA=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 13 ++++- app_linux.go | 7 +++ backend/data/alert_windows_api.go | 13 +++-- backend/data/dingding_api.go | 16 +++++-- backend/data/settings_api.go | 44 +++++++++++++++++ frontend/src/App.vue | 6 +-- frontend/src/components/settings.vue | 71 +++++++++++++++++++++++++--- frontend/src/components/stock.vue | 2 +- frontend/wailsjs/go/main/App.d.ts | 4 ++ frontend/wailsjs/go/main/App.js | 8 ++++ frontend/wailsjs/go/models.ts | 45 ++++++++++++++++++ main.go | 3 +- 12 files changed, 211 insertions(+), 21 deletions(-) create mode 100644 backend/data/settings_api.go diff --git a/app.go b/app.go index c6b4f26..6896ed4 100644 --- a/app.go +++ b/app.go @@ -146,9 +146,9 @@ func GetStockInfos(follows ...data.FollowedStock) *[]data.StockInfo { func getStockInfo(follow data.FollowedStock) *data.StockInfo { stockCode := follow.StockCode stockDatas, err := data.NewStockDataApi().GetStockCodeRealTimeData(stockCode) - if err != nil { + if err != nil || len(*stockDatas) == 0 { logger.SugaredLogger.Errorf("get stock code real time data error:%s", err.Error()) - return nil + return &data.StockInfo{} } stockData := (*stockDatas)[0] addStockFollowData(follow, &stockData) @@ -413,3 +413,12 @@ func onReady(a *App) { } }() } + +func (a *App) UpdateConfig(settings *data.Settings) string { + logger.SugaredLogger.Infof("UpdateConfig:%+v", settings) + return data.NewSettingsApi(settings).UpdateConfig() +} + +func (a *App) GetConfig() *data.Settings { + return data.NewSettingsApi(&data.Settings{}).GetConfig() +} diff --git a/app_linux.go b/app_linux.go index 986e1e8..a333df1 100644 --- a/app_linux.go +++ b/app_linux.go @@ -184,3 +184,10 @@ func getMsgTypeName(msgType int) string { return "未知类型" } } +func (a *App) UpdateConfig(settings *data.Settings) string { + return data.NewSettingsApi(settings).UpdateConfig() +} + +func (a *App) GetConfig() *data.Settings { + return data.NewSettingsApi(&data.Settings{}).GetConfig() +} diff --git a/backend/data/alert_windows_api.go b/backend/data/alert_windows_api.go index e2ed65a..76ff0e3 100644 --- a/backend/data/alert_windows_api.go +++ b/backend/data/alert_windows_api.go @@ -11,7 +11,7 @@ import ( // @Date 2025/1/8 9:40 // @Desc // ----------------------------------------------------------------------------------- -type alertWindowsApi struct { +type AlertWindowsApi struct { AppID string // 窗口标题 Title string @@ -21,8 +21,8 @@ type alertWindowsApi struct { Icon string } -func NewAlertWindowsApi(AppID string, Title string, Content string, Icon string) *alertWindowsApi { - return &alertWindowsApi{ +func NewAlertWindowsApi(AppID string, Title string, Content string, Icon string) *AlertWindowsApi { + return &AlertWindowsApi{ AppID: AppID, Title: Title, Content: Content, @@ -30,7 +30,12 @@ func NewAlertWindowsApi(AppID string, Title string, Content string, Icon string) } } -func (a alertWindowsApi) SendNotification() bool { +func (a AlertWindowsApi) SendNotification() bool { + if getConfig().LocalPushEnable == false { + logger.SugaredLogger.Error("本地推送未开启") + return false + } + notification := toast.Notification{ AppID: a.AppID, Title: a.Title, diff --git a/backend/data/dingding_api.go b/backend/data/dingding_api.go index b591373..a5ed6be 100644 --- a/backend/data/dingding_api.go +++ b/backend/data/dingding_api.go @@ -10,8 +10,6 @@ import ( // @Desc //----------------------------------------------------------------------------------- -const dingding_robot_url = "https://oapi.dingtalk.com/robot/send?access_token=0237527b404598f37ae5d83ef36e936860c7ba5d3892cd43f64c4159d3ed7cb1" - type DingDingAPI struct { client *resty.Client } @@ -23,11 +21,15 @@ func NewDingDingAPI() *DingDingAPI { } func (DingDingAPI) SendDingDingMessage(message string) string { + if getConfig().DingPushEnable == false { + logger.SugaredLogger.Info("钉钉推送未开启") + return "钉钉推送未开启" + } // 发送钉钉消息 resp, err := resty.New().R(). SetHeader("Content-Type", "application/json"). SetBody(message). - Post(dingding_robot_url) + Post(getApiURL()) if err != nil { logger.SugaredLogger.Error(err.Error()) return "发送钉钉消息失败" @@ -35,6 +37,12 @@ func (DingDingAPI) SendDingDingMessage(message string) string { logger.SugaredLogger.Infof("send dingding message: %s", resp.String()) return "发送钉钉消息成功" } +func getConfig() *Settings { + return NewSettingsApi(&Settings{}).GetConfig() +} +func getApiURL() string { + return getConfig().DingRobot +} func (DingDingAPI) SendToDingDing(title, message string) string { // 发送钉钉消息 @@ -50,7 +58,7 @@ func (DingDingAPI) SendToDingDing(title, message string) string { IsAtAll: true, }, }). - Post(dingding_robot_url) + Post(getApiURL()) if err != nil { logger.SugaredLogger.Error(err.Error()) return "发送钉钉消息失败" diff --git a/backend/data/settings_api.go b/backend/data/settings_api.go new file mode 100644 index 0000000..516184d --- /dev/null +++ b/backend/data/settings_api.go @@ -0,0 +1,44 @@ +package data + +import ( + "go-stock/backend/db" + "gorm.io/gorm" +) + +type Settings struct { + gorm.Model + LocalPushEnable bool `json:"localPushEnable"` + DingPushEnable bool `json:"dingPushEnable"` + DingRobot string `json:"dingRobot"` +} + +func (receiver Settings) TableName() string { + return "settings" +} + +type SettingsApi struct { + Config Settings +} + +func NewSettingsApi(settings *Settings) *SettingsApi { + return &SettingsApi{ + Config: *settings, + } +} + +func (s SettingsApi) UpdateConfig() string { + err := db.Dao.Model(s.Config).Updates(map[string]any{ + "local_push_enable": s.Config.LocalPushEnable, + "ding_push_enable": s.Config.DingPushEnable, + "ding_robot": s.Config.DingRobot, + }).Error + if err != nil { + return err.Error() + } + return "保存成功!" +} +func (s SettingsApi) GetConfig() *Settings { + var settings Settings + db.Dao.Model(&Settings{}).First(&settings) + return &settings +} diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 4d5e414..9c4d509 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -108,10 +108,10 @@ function toggleFullscreen(e) { :content="content" cross selectable - :font-size="12" - :line-height="12" + :font-size="18" + :line-height="18" :height="400" - :width="200" + :width="600" :x-offset="50" :y-offset="50" :rotate="-15" diff --git a/frontend/src/components/settings.vue b/frontend/src/components/settings.vue index ea19a0c..da33b56 100644 --- a/frontend/src/components/settings.vue +++ b/frontend/src/components/settings.vue @@ -1,26 +1,78 @@ diff --git a/frontend/src/components/stock.vue b/frontend/src/components/stock.vue index 87848fc..8261d57 100644 --- a/frontend/src/components/stock.vue +++ b/frontend/src/components/stock.vue @@ -343,7 +343,7 @@ function SendMessage(result,type){ "- 成本数量: "+result.costVolume+"股\n" + "- 日期: "+result["日期"]+" "+result["时间"]+"\n\n"+ "![image]("+img+")\n" - let title=result["股票名称"]+"("+result["股票代码"]+") "+result["当前价格"]+" "+result.s + let title=result["股票名称"]+"("+result["股票代码"]+") "+result["当前价格"]+" "+result.changePercent let msg='{' + ' "msgtype": "markdown",' + diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index e7c8dc3..a03b394 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -4,6 +4,8 @@ import {data} from '../models'; export function Follow(arg1:string):Promise; +export function GetConfig():Promise; + export function GetFollowList():Promise>; export function GetStockList(arg1:string):Promise>; @@ -21,3 +23,5 @@ export function SetCostPriceAndVolume(arg1:string,arg2:number,arg3:number):Promi export function SetStockSort(arg1:number,arg2:string):Promise; export function UnFollow(arg1:string):Promise; + +export function UpdateConfig(arg1:data.Settings):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 06097eb..0c11ea9 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -6,6 +6,10 @@ export function Follow(arg1) { return window['go']['main']['App']['Follow'](arg1); } +export function GetConfig() { + return window['go']['main']['App']['GetConfig'](); +} + export function GetFollowList() { return window['go']['main']['App']['GetFollowList'](); } @@ -41,3 +45,7 @@ export function SetStockSort(arg1, arg2) { export function UnFollow(arg1) { return window['go']['main']['App']['UnFollow'](arg1); } + +export function UpdateConfig(arg1) { + return window['go']['main']['App']['UpdateConfig'](arg1); +} diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 8cf1279..026d4d6 100644 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -53,6 +53,51 @@ export namespace data { return a; } } + export class Settings { + ID: number; + // Go type: time + CreatedAt: any; + // Go type: time + UpdatedAt: any; + // Go type: gorm + DeletedAt: any; + localPushEnable: boolean; + dingPushEnable: boolean; + dingRobot: string; + + static createFrom(source: any = {}) { + return new Settings(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.ID = source["ID"]; + this.CreatedAt = this.convertValues(source["CreatedAt"], null); + this.UpdatedAt = this.convertValues(source["UpdatedAt"], null); + this.DeletedAt = this.convertValues(source["DeletedAt"], null); + this.localPushEnable = source["localPushEnable"]; + this.dingPushEnable = source["dingPushEnable"]; + this.dingRobot = source["dingRobot"]; + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } export class StockBasic { ID: number; // Go type: time diff --git a/main.go b/main.go index 4b6e617..83f0a59 100644 --- a/main.go +++ b/main.go @@ -40,11 +40,12 @@ func main() { db.Dao.AutoMigrate(&data.StockBasic{}) db.Dao.AutoMigrate(&data.FollowedStock{}) db.Dao.AutoMigrate(&data.IndexBasic{}) + db.Dao.AutoMigrate(&data.Settings{}) if stocksBin != nil && len(stocksBin) > 0 { go initStockData() } - updateBasicInfo() + //updateBasicInfo() // Create an instance of the app structure app := NewApp()