diff --git a/.gitignore b/.gitignore
index 54cbb24..75f573e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,6 +107,6 @@ dist
.idea/
data/*.db
-build/*.exe
-/build/bin/go-stock-dev.exe
-/build/bin/
+./build/*.exe
+./build/bin/go-stock-dev.exe
+./build/bin/go-stock.exe
diff --git a/app.go b/app.go
index 52b3d3e..932aafd 100644
--- a/app.go
+++ b/app.go
@@ -2,6 +2,8 @@ package main
import (
"context"
+ "github.com/coocood/freecache"
+ "github.com/getlantern/systray"
"github.com/wailsapp/wails/v2/pkg/runtime"
"go-stock/backend/data"
"go-stock/backend/logger"
@@ -9,18 +11,31 @@ import (
// App struct
type App struct {
- ctx context.Context
+ ctx context.Context
+ cache *freecache.Cache
}
// NewApp creates a new App application struct
func NewApp() *App {
- return &App{}
+ cacheSize := 512 * 1024
+ cache := freecache.NewCache(cacheSize)
+ return &App{
+ cache: cache,
+ }
}
// startup is called at application startup
func (a *App) startup(ctx context.Context) {
// Perform your setup here
a.ctx = ctx
+
+ // 创建系统托盘
+ go systray.Run(func() {
+ onReady(a)
+ }, func() {
+ onExit(a)
+ })
+
}
// domReady is called after front-end resources have been loaded
@@ -63,6 +78,7 @@ func (a *App) beforeClose(ctx context.Context) (prevent bool) {
// shutdown is called at application termination
func (a *App) shutdown(ctx context.Context) {
// Perform your teardown here
+ systray.Quit()
}
// Greet returns a greeting for the given name
@@ -90,3 +106,59 @@ func (a *App) GetStockList(key string) []data.StockBasic {
func (a *App) SetCostPriceAndVolume(stockCode string, price float64, volume int64) string {
return data.NewStockDataApi().SetCostPriceAndVolume(price, volume, stockCode)
}
+
+func (a *App) SetAlarmChangePercent(val float64, stockCode string) string {
+ return data.NewStockDataApi().SetAlarmChangePercent(val, stockCode)
+}
+
+func (a *App) SendDingDingMessage(message string, stockCode string) string {
+ ttl, _ := a.cache.TTL([]byte(stockCode))
+ logger.SugaredLogger.Infof("stockCode %s ttl:%d", stockCode, ttl)
+ if ttl > 0 {
+ return ""
+ }
+ err := a.cache.Set([]byte(stockCode), []byte("1"), 60*5)
+ if err != nil {
+ logger.SugaredLogger.Errorf("set cache error:%s", err.Error())
+ return ""
+ }
+ return data.NewDingDingAPI().SendDingDingMessage(message)
+}
+
+func onExit(a *App) {
+ // 清理操作
+ logger.SugaredLogger.Infof("onExit")
+ runtime.Quit(a.ctx)
+}
+
+func onReady(a *App) {
+ // 初始化操作
+ logger.SugaredLogger.Infof("onReady")
+ systray.SetIcon(icon2)
+ systray.SetTitle("go-stock")
+ systray.SetTooltip("这是一个简单的系统托盘示例")
+ // 创建菜单项
+ mQuitOrig := systray.AddMenuItem("退出", "退出应用程序")
+ show := systray.AddMenuItem("显示", "显示应用程序")
+ hide := systray.AddMenuItem("隐藏应用程序", "隐藏应用程序")
+
+ // 监听菜单项点击事件
+ go func() {
+ for {
+ select {
+ case <-mQuitOrig.ClickedCh:
+ logger.SugaredLogger.Infof("退出应用程序")
+ runtime.Quit(a.ctx)
+ systray.Quit()
+ case <-show.ClickedCh:
+ logger.SugaredLogger.Infof("显示应用程序")
+ runtime.Show(a.ctx)
+ //runtime.WindowShow(a.ctx)
+ case <-hide.ClickedCh:
+ logger.SugaredLogger.Infof("隐藏应用程序")
+ runtime.Hide(a.ctx)
+
+ }
+ }
+ }()
+}
diff --git a/backend/data/dingding_api.go b/backend/data/dingding_api.go
new file mode 100644
index 0000000..b591373
--- /dev/null
+++ b/backend/data/dingding_api.go
@@ -0,0 +1,77 @@
+package data
+
+import (
+ "github.com/go-resty/resty/v2"
+ "go-stock/backend/logger"
+)
+
+// @Author spark
+// @Date 2025/1/3 13:53
+// @Desc
+//-----------------------------------------------------------------------------------
+
+const dingding_robot_url = "https://oapi.dingtalk.com/robot/send?access_token=0237527b404598f37ae5d83ef36e936860c7ba5d3892cd43f64c4159d3ed7cb1"
+
+type DingDingAPI struct {
+ client *resty.Client
+}
+
+func NewDingDingAPI() *DingDingAPI {
+ return &DingDingAPI{
+ client: resty.New(),
+ }
+}
+
+func (DingDingAPI) SendDingDingMessage(message string) string {
+ // 发送钉钉消息
+ resp, err := resty.New().R().
+ SetHeader("Content-Type", "application/json").
+ SetBody(message).
+ Post(dingding_robot_url)
+ if err != nil {
+ logger.SugaredLogger.Error(err.Error())
+ return "发送钉钉消息失败"
+ }
+ logger.SugaredLogger.Infof("send dingding message: %s", resp.String())
+ return "发送钉钉消息成功"
+}
+
+func (DingDingAPI) SendToDingDing(title, message string) string {
+ // 发送钉钉消息
+ resp, err := resty.New().R().
+ SetHeader("Content-Type", "application/json").
+ SetBody(&Message{
+ Msgtype: "markdown",
+ Markdown: Markdown{
+ Title: "go-stock " + title,
+ Text: message,
+ },
+ At: At{
+ IsAtAll: true,
+ },
+ }).
+ Post(dingding_robot_url)
+ if err != nil {
+ logger.SugaredLogger.Error(err.Error())
+ return "发送钉钉消息失败"
+ }
+ logger.SugaredLogger.Infof("send dingding message: %s", resp.String())
+ return "发送钉钉消息成功"
+}
+
+type Message struct {
+ Msgtype string `json:"msgtype"`
+ Markdown Markdown `json:"markdown"`
+ At At `json:"at"`
+}
+
+type Markdown struct {
+ Title string `json:"title"`
+ Text string `json:"text"`
+}
+
+type At struct {
+ AtMobiles []string `json:"atMobiles"`
+ AtUserIds []string `json:"atUserIds"`
+ IsAtAll bool `json:"isAtAll"`
+}
diff --git a/backend/data/dingding_api_test.go b/backend/data/dingding_api_test.go
new file mode 100644
index 0000000..72a0e4f
--- /dev/null
+++ b/backend/data/dingding_api_test.go
@@ -0,0 +1,31 @@
+package data
+
+import (
+ "github.com/go-resty/resty/v2"
+ "testing"
+)
+
+// @Author spark
+// @Date 2025/1/3 13:53
+// @Desc
+//-----------------------------------------------------------------------------------
+
+func TestRobot(t *testing.T) {
+ resp, err := resty.New().R().
+ SetHeader("Content-Type", "application/json").
+ SetBody(`{
+ "msgtype": "markdown",
+ "markdown": {
+ "title":"go-stock",
+ "text": "#### 杭州天气 @150XXXXXXXX \n > 9度,西北风1级,空气良89,相对温度73%\n > \n > ###### 10点20分发布 [天气](https://www.dingtalk.com) \n"
+ },
+ "at": {
+ "isAtAll": true
+ }
+ }`).
+ Post(dingding_robot_url)
+ if err != nil {
+ t.Error(err)
+ }
+ t.Log(resp.String())
+}
diff --git a/backend/data/stock_data_api.go b/backend/data/stock_data_api.go
index fc8ed9d..9b309ba 100644
--- a/backend/data/stock_data_api.go
+++ b/backend/data/stock_data_api.go
@@ -9,6 +9,7 @@ import (
"encoding/json"
"fmt"
"github.com/duke-git/lancet/v2/convertor"
+ "github.com/duke-git/lancet/v2/slice"
"github.com/duke-git/lancet/v2/strutil"
"github.com/go-resty/resty/v2"
"go-stock/backend/db"
@@ -126,16 +127,17 @@ type StockBasic struct {
}
type FollowedStock struct {
- StockCode string
- Name string
- Volume int64
- CostPrice float64
- Price float64
- PriceChange float64
- ChangePercent float64
- Time time.Time
- Sort int64
- IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
+ StockCode string
+ Name string
+ Volume int64
+ CostPrice float64
+ Price float64
+ PriceChange float64
+ ChangePercent float64
+ AlarmChangePercent float64
+ Time time.Time
+ Sort int64
+ IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
}
func (receiver FollowedStock) TableName() string {
@@ -162,21 +164,68 @@ func NewStockDataApi() *StockDataApi {
client: resty.New(),
}
}
+
+// GetIndexBasic 获取指数信息
+func (receiver StockDataApi) GetIndexBasic() {
+ res := &TushareStockBasicResponse{}
+ fields := "ts_code,name,market,publisher,category,base_date,base_point,list_date,fullname,index_type,weight_rule,desc"
+ _, err := receiver.client.R().
+ SetHeader("content-type", "application/json").
+ SetBody(&TushareRequest{
+ ApiName: "index_basic",
+ Token: TushareToken,
+ Params: nil,
+ Fields: fields}).
+ SetResult(res).
+ Post(tushare_api_url)
+ if err != nil {
+ logger.SugaredLogger.Error(err.Error())
+ return
+ }
+ if res.Code != 0 {
+ logger.SugaredLogger.Error(res.Msg)
+ return
+ }
+ //ioutil.WriteFile("index_basic.json", resp.Body(), 0666)
+
+ for _, item := range res.Data.Items {
+ data := map[string]any{}
+ for _, field := range strings.Split(fields, ",") {
+ idx := slice.IndexOf(res.Data.Fields, field)
+ if idx == -1 {
+ continue
+ }
+ data[field] = item[idx]
+ }
+ index := &IndexBasic{}
+ jsonData, _ := json.Marshal(data)
+ err := json.Unmarshal(jsonData, index)
+ if err != nil {
+ continue
+ }
+ db.Dao.Model(&IndexBasic{}).FirstOrCreate(index, &IndexBasic{TsCode: index.TsCode}).Where("ts_code = ?", index.TsCode).Updates(index)
+ }
+
+}
+
+// map转换为结构体
+
func (receiver StockDataApi) GetStockBaseInfo() {
res := &TushareStockBasicResponse{}
- resp, err := receiver.client.R().
+ fields := "ts_code,symbol,name,area,industry,cnspell,market,list_date,act_name,act_ent_type,fullname,exchange,list_status,curr_type,enname,delist_date,is_hs"
+ _, err := receiver.client.R().
SetHeader("content-type", "application/json").
SetBody(&TushareRequest{
ApiName: "stock_basic",
Token: TushareToken,
Params: nil,
- Fields: "*",
+ Fields: fields,
}).
SetResult(res).
Post(tushare_api_url)
//logger.SugaredLogger.Infof("GetStockBaseInfo %s", string(resp.Body()))
//resp.Body()写入文件
- ioutil.WriteFile("stock_basic.json", resp.Body(), 0666)
+ //ioutil.WriteFile("stock_basic.json", resp.Body(), 0666)
//logger.SugaredLogger.Infof("GetStockBaseInfo %+v", res)
if err != nil {
logger.SugaredLogger.Error(err.Error())
@@ -187,26 +236,22 @@ func (receiver StockDataApi) GetStockBaseInfo() {
return
}
for _, item := range res.Data.Items {
- ID, _ := convertor.ToInt(item[6])
stock := &StockBasic{}
- stock.Exchange = convertor.ToString(item[0])
- stock.IsHs = convertor.ToString(item[1])
- stock.Name = convertor.ToString(item[2])
- stock.Industry = convertor.ToString(item[3])
- stock.ListStatus = convertor.ToString(item[4])
- stock.ActName = convertor.ToString(item[5])
- stock.ID = uint(ID)
- stock.CurrType = convertor.ToString(item[7])
- stock.Area = convertor.ToString(item[8])
- stock.ListDate = convertor.ToString(item[9])
- stock.DelistDate = convertor.ToString(item[10])
- stock.ActEntType = convertor.ToString(item[11])
- stock.TsCode = convertor.ToString(item[12])
- stock.Symbol = convertor.ToString(item[13])
- stock.Cnspell = convertor.ToString(item[14])
- stock.Fullname = convertor.ToString(item[20])
- stock.Ename = convertor.ToString(item[21])
- db.Dao.Model(&StockBasic{}).FirstOrCreate(stock, &StockBasic{TsCode: stock.TsCode}).Updates(stock)
+ data := map[string]any{}
+ for _, field := range strings.Split(fields, ",") {
+ logger.SugaredLogger.Infof("field: %s", field)
+ idx := slice.IndexOf(res.Data.Fields, field)
+ if idx == -1 {
+ continue
+ }
+ data[field] = item[idx]
+ }
+ jsonData, _ := json.Marshal(data)
+ err := json.Unmarshal(jsonData, stock)
+ if err != nil {
+ continue
+ }
+ db.Dao.Model(&StockBasic{}).FirstOrCreate(stock, &StockBasic{TsCode: stock.TsCode}).Where("ts_code = ?", stock.TsCode).Updates(stock)
}
}
@@ -233,6 +278,7 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCode string) (*StockI
}
func (receiver StockDataApi) Follow(stockCode string) string {
+ logger.SugaredLogger.Infof("Follow %s", stockCode)
stockInfo, err := receiver.GetStockCodeRealTimeData(stockCode)
if err != nil {
logger.SugaredLogger.Error(err.Error())
@@ -264,6 +310,15 @@ func (receiver StockDataApi) SetCostPriceAndVolume(price float64, volume int64,
return "设置成功"
}
+func (receiver StockDataApi) SetAlarmChangePercent(val float64, stockCode string) string {
+ err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Update("alarm_change_percent", val).Error
+ if err != nil {
+ logger.SugaredLogger.Error(err.Error())
+ return "设置失败"
+ }
+ return "设置成功"
+}
+
func (receiver StockDataApi) GetFollowList() []FollowedStock {
var result []FollowedStock
db.Dao.Model(&FollowedStock{}).Order("sort asc,time desc").Find(&result)
@@ -273,6 +328,20 @@ func (receiver StockDataApi) GetFollowList() []FollowedStock {
func (receiver StockDataApi) GetStockList(key string) []StockBasic {
var result []StockBasic
db.Dao.Model(&StockBasic{}).Where("name like ? or ts_code like ?", "%"+key+"%", "%"+key+"%").Find(&result)
+ var result2 []IndexBasic
+ db.Dao.Model(&IndexBasic{}).Where("market in ?", []string{"SSE", "SZSE"}).Where("name like ? or ts_code like ?", "%"+key+"%", "%"+key+"%").Find(&result2)
+
+ for _, item := range result2 {
+ result = append(result, StockBasic{
+ TsCode: item.TsCode,
+ Name: item.Name,
+ Fullname: item.FullName,
+ Symbol: item.Symbol,
+ Market: item.Market,
+ ListDate: item.ListDate,
+ })
+ }
+
return result
}
@@ -371,3 +440,24 @@ func ParseFullSingleStockData(data string) (*StockInfo, error) {
return stockInfo, nil
}
+
+type IndexBasic struct {
+ gorm.Model
+ TsCode string `json:"ts_code" gorm:"index"`
+ Symbol string `json:"symbol" gorm:"index"`
+ Name string `json:"name" gorm:"index"`
+ FullName string `json:"fullname"`
+ IndexType string `json:"index_type"`
+ IndexCategory string `json:"category"`
+ Market string `json:"market"`
+ ListDate string `json:"list_date"`
+ BaseDate string `json:"base_date"`
+ BasePoint float64 `json:"base_point"`
+ Publisher string `json:"publisher"`
+ WeightRule string `json:"weight_rule"`
+ DESC string `json:"desc"`
+}
+
+func (IndexBasic) TableName() string {
+ return "tushare_index_basic"
+}
diff --git a/backend/data/stock_data_api_test.go b/backend/data/stock_data_api_test.go
index 7e88a64..6d5ca87 100644
--- a/backend/data/stock_data_api_test.go
+++ b/backend/data/stock_data_api_test.go
@@ -77,3 +77,9 @@ func TestFollowedList(t *testing.T) {
t.Log(stockDataApi.GetFollowList())
}
+
+func TestStockDataApi_GetIndexBasic(t *testing.T) {
+ db.Init("../../data/stock.db")
+ stockDataApi := NewStockDataApi()
+ stockDataApi.GetIndexBasic()
+}
diff --git a/build/app.ico b/build/app.ico
new file mode 100644
index 0000000..b261d41
Binary files /dev/null and b/build/app.ico differ
diff --git a/build/bin/go-stock.exe b/build/bin/go-stock.exe
deleted file mode 100644
index 511db66..0000000
Binary files a/build/bin/go-stock.exe and /dev/null differ
diff --git a/frontend/src/components/stock.vue b/frontend/src/components/stock.vue
index 739098c..ec2203f 100644
--- a/frontend/src/components/stock.vue
+++ b/frontend/src/components/stock.vue
@@ -1,6 +1,14 @@
@@ -289,7 +353,7 @@ function fullscreen(){
分时
日K
详情
-
+
@@ -305,8 +369,8 @@ function fullscreen(){
autocomplete: 'disabled',
}"
:options="options"
- placeholder="请输入股票名称或者代码"
- clearable @input="getStockList" :on-select="onSelect"/>
+ placeholder="请输入股票/指数名称或者代码"
+ clearable @update-value="getStockList" :on-select="onSelect"/>
关注该股票
@@ -315,16 +379,31 @@ function fullscreen(){
-
-
-
+
+
+
+
+ 元
+
+
-
-
+
+
+
+ 股
+
+
+
+
+
+
+ %
+
+
- 保存
+ 保存
diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts
index 11f153e..150cab0 100644
--- a/frontend/wailsjs/go/main/App.d.ts
+++ b/frontend/wailsjs/go/main/App.d.ts
@@ -10,6 +10,10 @@ export function GetStockList(arg1:string):Promise>;
export function Greet(arg1:string):Promise;
+export function SendDingDingMessage(arg1:string,arg2:string):Promise;
+
+export function SetAlarmChangePercent(arg1:number,arg2:string):Promise;
+
export function SetCostPriceAndVolume(arg1:string,arg2:number,arg3:number):Promise;
export function UnFollow(arg1:string):Promise;
diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js
index e7396db..745ac69 100644
--- a/frontend/wailsjs/go/main/App.js
+++ b/frontend/wailsjs/go/main/App.js
@@ -18,6 +18,14 @@ export function Greet(arg1) {
return window['go']['main']['App']['Greet'](arg1);
}
+export function SendDingDingMessage(arg1, arg2) {
+ return window['go']['main']['App']['SendDingDingMessage'](arg1, arg2);
+}
+
+export function SetAlarmChangePercent(arg1, arg2) {
+ return window['go']['main']['App']['SetAlarmChangePercent'](arg1, arg2);
+}
+
export function SetCostPriceAndVolume(arg1, arg2, arg3) {
return window['go']['main']['App']['SetCostPriceAndVolume'](arg1, arg2, arg3);
}
diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts
index 96143c8..b01da60 100644
--- a/frontend/wailsjs/go/models.ts
+++ b/frontend/wailsjs/go/models.ts
@@ -8,6 +8,7 @@ export namespace data {
Price: number;
PriceChange: number;
ChangePercent: number;
+ AlarmChangePercent: number;
// Go type: time
Time: any;
Sort: number;
@@ -26,6 +27,7 @@ export namespace data {
this.Price = source["Price"];
this.PriceChange = source["PriceChange"];
this.ChangePercent = source["ChangePercent"];
+ this.AlarmChangePercent = source["AlarmChangePercent"];
this.Time = this.convertValues(source["Time"], null);
this.Sort = source["Sort"];
this.IsDel = source["IsDel"];
diff --git a/go.mod b/go.mod
index 174e3d0..8843abf 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,9 @@ go 1.21
toolchain go1.23.0
require (
+ github.com/coocood/freecache v1.2.4
github.com/duke-git/lancet/v2 v2.3.4
+ github.com/getlantern/systray v1.2.2
github.com/glebarez/sqlite v1.11.0
github.com/go-resty/resty/v2 v2.16.2
github.com/wailsapp/wails/v2 v2.9.2
@@ -19,9 +21,17 @@ require (
require (
github.com/bep/debounce v1.2.1 // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
+ github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
+ github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect
+ github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 // indirect
+ github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect
+ github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect
+ github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-stack/stack v1.8.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
@@ -35,6 +45,7 @@ require (
github.com/leaanthony/u v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
diff --git a/go.sum b/go.sum
index eb769d9..a64c8c2 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,9 @@
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/coocood/freecache v1.2.4 h1:UdR6Yz/X1HW4fZOuH0Z94KwG851GWOSknua5VUbb/5M=
+github.com/coocood/freecache v1.2.4/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -7,6 +11,20 @@ github.com/duke-git/lancet/v2 v2.3.4 h1:8XGI7P9w+/GqmEBEXYaH/XuNiM0f4/90Ioti0IvY
github.com/duke-git/lancet/v2 v2.3.4/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
+github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
+github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So=
+github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
+github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 h1:guBYzEaLz0Vfc/jv0czrr2z7qyzTOGC9hiQ0VC+hKjk=
+github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7/go.mod h1:zx/1xUUeYPy3Pcmet8OSXLbF47l+3y6hIPpyLWoR9oc=
+github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0=
+github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
+github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc=
+github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
+github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
+github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
+github.com/getlantern/systray v1.2.2 h1:dCEHtfmvkJG7HZ8lS/sLklTH4RKUcIsKrAD9sThoEBE=
+github.com/getlantern/systray v1.2.2/go.mod h1:pXFOI1wwqwYXEhLPm9ZGjS2u/vVELeIgNMY5HvhHhcE=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
@@ -17,6 +35,8 @@ github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CA
github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
@@ -46,6 +66,8 @@ github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI=
github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
+github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
+github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
@@ -58,6 +80,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
+github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
+github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -72,7 +96,9 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
+github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
@@ -117,6 +143,7 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -127,6 +154,7 @@ golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
@@ -149,6 +177,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
diff --git a/main.go b/main.go
index 3e5e2fe..a384fda 100644
--- a/main.go
+++ b/main.go
@@ -25,6 +25,9 @@ var assets embed.FS
//go:embed build/appicon.png
var icon []byte
+//go:embed build/app.ico
+var icon2 []byte
+
//go:embed build/stock_basic.json
var stocksBin []byte
@@ -35,11 +38,13 @@ func main() {
db.Dao.AutoMigrate(&data.StockInfo{})
db.Dao.AutoMigrate(&data.StockBasic{})
db.Dao.AutoMigrate(&data.FollowedStock{})
+ db.Dao.AutoMigrate(&data.IndexBasic{})
if stocksBin != nil && len(stocksBin) > 0 {
go initStockData()
}
go data.NewStockDataApi().GetStockBaseInfo()
+ go data.NewStockDataApi().GetIndexBasic()
// Create an instance of the app structure
app := NewApp()
@@ -63,9 +68,13 @@ func main() {
FileMenu.AddText("窗口还原", keys.Key("Esc"), func(callback *menu.CallbackData) {
runtime.WindowUnfullscreen(app.ctx)
})
+ FileMenu.AddText("隐藏到托盘区", keys.CmdOrCtrl("h"), func(_ *menu.CallbackData) {
+ runtime.Hide(app.ctx)
+ })
FileMenu.AddText("退出", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
runtime.Quit(app.ctx)
})
+
// Create application with options
err := wails.Run(&options.App{
Title: "go-stock",
diff --git a/stock_basic.json b/stock_basic.json
deleted file mode 100644
index c9a1711..0000000
--- a/stock_basic.json
+++ /dev/null
@@ -1 +0,0 @@
-{"request_id":"bf5b7774-d16d-43fe-9806-dff9ef37cd33","code":40203,"data":null,"msg":"抱歉,您每小时最多访问该接口1次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。"}
\ No newline at end of file