mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
Merge branch 'master' of https://github.com/ArvinLovegood/go-stock
# Conflicts: # stock_basic.json
This commit is contained in:
commit
1e5d9bc469
6
.gitignore
vendored
6
.gitignore
vendored
@ -107,6 +107,6 @@ dist
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
data/*.db
|
data/*.db
|
||||||
build/*.exe
|
./build/*.exe
|
||||||
/build/bin/go-stock-dev.exe
|
./build/bin/go-stock-dev.exe
|
||||||
/build/bin/
|
./build/bin/go-stock.exe
|
||||||
|
76
app.go
76
app.go
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/coocood/freecache"
|
||||||
|
"github.com/getlantern/systray"
|
||||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||||
"go-stock/backend/data"
|
"go-stock/backend/data"
|
||||||
"go-stock/backend/logger"
|
"go-stock/backend/logger"
|
||||||
@ -9,18 +11,31 @@ import (
|
|||||||
|
|
||||||
// App struct
|
// App struct
|
||||||
type App struct {
|
type App struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
cache *freecache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewApp creates a new App application struct
|
// NewApp creates a new App application struct
|
||||||
func NewApp() *App {
|
func NewApp() *App {
|
||||||
return &App{}
|
cacheSize := 512 * 1024
|
||||||
|
cache := freecache.NewCache(cacheSize)
|
||||||
|
return &App{
|
||||||
|
cache: cache,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// startup is called at application startup
|
// startup is called at application startup
|
||||||
func (a *App) startup(ctx context.Context) {
|
func (a *App) startup(ctx context.Context) {
|
||||||
// Perform your setup here
|
// Perform your setup here
|
||||||
a.ctx = ctx
|
a.ctx = ctx
|
||||||
|
|
||||||
|
// 创建系统托盘
|
||||||
|
go systray.Run(func() {
|
||||||
|
onReady(a)
|
||||||
|
}, func() {
|
||||||
|
onExit(a)
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// domReady is called after front-end resources have been loaded
|
// 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
|
// shutdown is called at application termination
|
||||||
func (a *App) shutdown(ctx context.Context) {
|
func (a *App) shutdown(ctx context.Context) {
|
||||||
// Perform your teardown here
|
// Perform your teardown here
|
||||||
|
systray.Quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Greet returns a greeting for the given name
|
// 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 {
|
func (a *App) SetCostPriceAndVolume(stockCode string, price float64, volume int64) string {
|
||||||
return data.NewStockDataApi().SetCostPriceAndVolume(price, volume, stockCode)
|
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)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
77
backend/data/dingding_api.go
Normal file
77
backend/data/dingding_api.go
Normal file
@ -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"`
|
||||||
|
}
|
31
backend/data/dingding_api_test.go
Normal file
31
backend/data/dingding_api_test.go
Normal file
@ -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())
|
||||||
|
}
|
@ -9,6 +9,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
"github.com/duke-git/lancet/v2/strutil"
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
"go-stock/backend/db"
|
"go-stock/backend/db"
|
||||||
@ -126,16 +127,17 @@ type StockBasic struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FollowedStock struct {
|
type FollowedStock struct {
|
||||||
StockCode string
|
StockCode string
|
||||||
Name string
|
Name string
|
||||||
Volume int64
|
Volume int64
|
||||||
CostPrice float64
|
CostPrice float64
|
||||||
Price float64
|
Price float64
|
||||||
PriceChange float64
|
PriceChange float64
|
||||||
ChangePercent float64
|
ChangePercent float64
|
||||||
Time time.Time
|
AlarmChangePercent float64
|
||||||
Sort int64
|
Time time.Time
|
||||||
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
|
Sort int64
|
||||||
|
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver FollowedStock) TableName() string {
|
func (receiver FollowedStock) TableName() string {
|
||||||
@ -162,21 +164,68 @@ func NewStockDataApi() *StockDataApi {
|
|||||||
client: resty.New(),
|
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() {
|
func (receiver StockDataApi) GetStockBaseInfo() {
|
||||||
res := &TushareStockBasicResponse{}
|
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").
|
SetHeader("content-type", "application/json").
|
||||||
SetBody(&TushareRequest{
|
SetBody(&TushareRequest{
|
||||||
ApiName: "stock_basic",
|
ApiName: "stock_basic",
|
||||||
Token: TushareToken,
|
Token: TushareToken,
|
||||||
Params: nil,
|
Params: nil,
|
||||||
Fields: "*",
|
Fields: fields,
|
||||||
}).
|
}).
|
||||||
SetResult(res).
|
SetResult(res).
|
||||||
Post(tushare_api_url)
|
Post(tushare_api_url)
|
||||||
//logger.SugaredLogger.Infof("GetStockBaseInfo %s", string(resp.Body()))
|
//logger.SugaredLogger.Infof("GetStockBaseInfo %s", string(resp.Body()))
|
||||||
//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)
|
//logger.SugaredLogger.Infof("GetStockBaseInfo %+v", res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.SugaredLogger.Error(err.Error())
|
logger.SugaredLogger.Error(err.Error())
|
||||||
@ -187,26 +236,22 @@ func (receiver StockDataApi) GetStockBaseInfo() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, item := range res.Data.Items {
|
for _, item := range res.Data.Items {
|
||||||
ID, _ := convertor.ToInt(item[6])
|
|
||||||
stock := &StockBasic{}
|
stock := &StockBasic{}
|
||||||
stock.Exchange = convertor.ToString(item[0])
|
data := map[string]any{}
|
||||||
stock.IsHs = convertor.ToString(item[1])
|
for _, field := range strings.Split(fields, ",") {
|
||||||
stock.Name = convertor.ToString(item[2])
|
logger.SugaredLogger.Infof("field: %s", field)
|
||||||
stock.Industry = convertor.ToString(item[3])
|
idx := slice.IndexOf(res.Data.Fields, field)
|
||||||
stock.ListStatus = convertor.ToString(item[4])
|
if idx == -1 {
|
||||||
stock.ActName = convertor.ToString(item[5])
|
continue
|
||||||
stock.ID = uint(ID)
|
}
|
||||||
stock.CurrType = convertor.ToString(item[7])
|
data[field] = item[idx]
|
||||||
stock.Area = convertor.ToString(item[8])
|
}
|
||||||
stock.ListDate = convertor.ToString(item[9])
|
jsonData, _ := json.Marshal(data)
|
||||||
stock.DelistDate = convertor.ToString(item[10])
|
err := json.Unmarshal(jsonData, stock)
|
||||||
stock.ActEntType = convertor.ToString(item[11])
|
if err != nil {
|
||||||
stock.TsCode = convertor.ToString(item[12])
|
continue
|
||||||
stock.Symbol = convertor.ToString(item[13])
|
}
|
||||||
stock.Cnspell = convertor.ToString(item[14])
|
db.Dao.Model(&StockBasic{}).FirstOrCreate(stock, &StockBasic{TsCode: stock.TsCode}).Where("ts_code = ?", stock.TsCode).Updates(stock)
|
||||||
stock.Fullname = convertor.ToString(item[20])
|
|
||||||
stock.Ename = convertor.ToString(item[21])
|
|
||||||
db.Dao.Model(&StockBasic{}).FirstOrCreate(stock, &StockBasic{TsCode: stock.TsCode}).Updates(stock)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -233,6 +278,7 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCode string) (*StockI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) Follow(stockCode string) string {
|
func (receiver StockDataApi) Follow(stockCode string) string {
|
||||||
|
logger.SugaredLogger.Infof("Follow %s", stockCode)
|
||||||
stockInfo, err := receiver.GetStockCodeRealTimeData(stockCode)
|
stockInfo, err := receiver.GetStockCodeRealTimeData(stockCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.SugaredLogger.Error(err.Error())
|
logger.SugaredLogger.Error(err.Error())
|
||||||
@ -264,6 +310,15 @@ func (receiver StockDataApi) SetCostPriceAndVolume(price float64, volume int64,
|
|||||||
return "设置成功"
|
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 {
|
func (receiver StockDataApi) GetFollowList() []FollowedStock {
|
||||||
var result []FollowedStock
|
var result []FollowedStock
|
||||||
db.Dao.Model(&FollowedStock{}).Order("sort asc,time desc").Find(&result)
|
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 {
|
func (receiver StockDataApi) GetStockList(key string) []StockBasic {
|
||||||
var result []StockBasic
|
var result []StockBasic
|
||||||
db.Dao.Model(&StockBasic{}).Where("name like ? or ts_code like ?", "%"+key+"%", "%"+key+"%").Find(&result)
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,3 +440,24 @@ func ParseFullSingleStockData(data string) (*StockInfo, error) {
|
|||||||
|
|
||||||
return stockInfo, nil
|
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"
|
||||||
|
}
|
||||||
|
@ -77,3 +77,9 @@ func TestFollowedList(t *testing.T) {
|
|||||||
t.Log(stockDataApi.GetFollowList())
|
t.Log(stockDataApi.GetFollowList())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStockDataApi_GetIndexBasic(t *testing.T) {
|
||||||
|
db.Init("../../data/stock.db")
|
||||||
|
stockDataApi := NewStockDataApi()
|
||||||
|
stockDataApi.GetIndexBasic()
|
||||||
|
}
|
||||||
|
BIN
build/app.ico
Normal file
BIN
build/app.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
@ -1,6 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
import {onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
||||||
import {Greet, Follow, UnFollow, GetFollowList, GetStockList, SetCostPriceAndVolume} from '../../wailsjs/go/main/App'
|
import {
|
||||||
|
Greet,
|
||||||
|
Follow,
|
||||||
|
UnFollow,
|
||||||
|
GetFollowList,
|
||||||
|
GetStockList,
|
||||||
|
SetCostPriceAndVolume,
|
||||||
|
SendDingDingMessage, SetAlarmChangePercent
|
||||||
|
} from '../../wailsjs/go/main/App'
|
||||||
import {NButton, NFlex, NForm, NFormItem, NInputNumber, NText, useMessage, useModal} from 'naive-ui'
|
import {NButton, NFlex, NForm, NFormItem, NInputNumber, NText, useMessage, useModal} from 'naive-ui'
|
||||||
import { WindowFullscreen,WindowUnfullscreen,EventsOn } from '../../wailsjs/runtime'
|
import { WindowFullscreen,WindowUnfullscreen,EventsOn } from '../../wailsjs/runtime'
|
||||||
import {Add, StarOutline} from '@vicons/ionicons5'
|
import {Add, StarOutline} from '@vicons/ionicons5'
|
||||||
@ -22,7 +30,8 @@ const formModel = ref({
|
|||||||
name: "",
|
name: "",
|
||||||
code: "",
|
code: "",
|
||||||
costPrice: 0.000,
|
costPrice: 0.000,
|
||||||
volume: 0
|
volume: 0,
|
||||||
|
alarm: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
@ -40,7 +49,7 @@ onBeforeMount(()=>{
|
|||||||
stockList.value = result
|
stockList.value = result
|
||||||
options.value=result.map(item => {
|
options.value=result.map(item => {
|
||||||
return {
|
return {
|
||||||
label: item.name+" "+item.ts_code,
|
label: item.name+" - "+item.ts_code,
|
||||||
value: item.ts_code
|
value: item.ts_code
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -64,8 +73,9 @@ onMounted(() => {
|
|||||||
ticker.value=setInterval(() => {
|
ticker.value=setInterval(() => {
|
||||||
if(isTradingTime()){
|
if(isTradingTime()){
|
||||||
monitor()
|
monitor()
|
||||||
|
data.fenshiURL='http://image.sinajs.cn/newchart/min/n/'+data.code+'.gif'+"?t="+Date.now()
|
||||||
}
|
}
|
||||||
}, 3000)
|
}, 3500)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -123,8 +133,10 @@ function AddStock(){
|
|||||||
Follow(data.code).then(result => {
|
Follow(data.code).then(result => {
|
||||||
message.success(result)
|
message.success(result)
|
||||||
})
|
})
|
||||||
|
monitor()
|
||||||
|
}else{
|
||||||
|
message.error("已经关注了")
|
||||||
}
|
}
|
||||||
monitor()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -138,21 +150,29 @@ function removeMonitor(code,name) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStockList(){
|
function getStockList(value){
|
||||||
|
console.log("getStockList",value)
|
||||||
let result;
|
let result;
|
||||||
result=stockList.value.filter(item => item.name.includes(data.name)||item.ts_code.includes(data.name))
|
result=stockList.value.filter(item => item.name.includes(data.name)||item.ts_code.includes(data.name))
|
||||||
options.value=result.map(item => {
|
options.value=result.map(item => {
|
||||||
return {
|
return {
|
||||||
label: item.name+" "+item.ts_code,
|
label: item.name+" - "+item.ts_code,
|
||||||
value: item.ts_code
|
value: item.ts_code
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if(value&&value.indexOf("-")<=0){
|
||||||
|
data.code=value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function monitor() {
|
async function monitor() {
|
||||||
for (let code of stocks.value) {
|
for (let code of stocks.value) {
|
||||||
// console.log(code)
|
// console.log(code)
|
||||||
Greet(code).then(result => {
|
Greet(code).then(result => {
|
||||||
|
if(result["当前价格"]<=0){
|
||||||
|
result["当前价格"]=result["卖一报价"]
|
||||||
|
}
|
||||||
|
|
||||||
let s=(result["当前价格"]-result["昨日收盘价"])*100/result["昨日收盘价"]
|
let s=(result["当前价格"]-result["昨日收盘价"])*100/result["昨日收盘价"]
|
||||||
let roundedNum = s.toFixed(2); // 将数字转换为保留两位小数的字符串形式
|
let roundedNum = s.toFixed(2); // 将数字转换为保留两位小数的字符串形式
|
||||||
result.s=roundedNum+"%"
|
result.s=roundedNum+"%"
|
||||||
@ -160,7 +180,6 @@ async function monitor() {
|
|||||||
result.highRate=((result["今日最高价"]-result["今日开盘价"])*100/result["今日开盘价"]).toFixed(2)+"%"
|
result.highRate=((result["今日最高价"]-result["今日开盘价"])*100/result["今日开盘价"]).toFixed(2)+"%"
|
||||||
result.lowRate=((result["今日最低价"]-result["今日开盘价"])*100/result["今日开盘价"]).toFixed(2)+"%"
|
result.lowRate=((result["今日最低价"]-result["今日开盘价"])*100/result["今日开盘价"]).toFixed(2)+"%"
|
||||||
|
|
||||||
|
|
||||||
if (roundedNum>0) {
|
if (roundedNum>0) {
|
||||||
result.type="error"
|
result.type="error"
|
||||||
result.color="#E88080"
|
result.color="#E88080"
|
||||||
@ -173,6 +192,7 @@ async function monitor() {
|
|||||||
}
|
}
|
||||||
let res= followList.value.filter(item => item.StockCode===code)
|
let res= followList.value.filter(item => item.StockCode===code)
|
||||||
if (res.length>0) {
|
if (res.length>0) {
|
||||||
|
result.Sort=res[0].Sort
|
||||||
result.costPrice=res[0].CostPrice
|
result.costPrice=res[0].CostPrice
|
||||||
result.volume=res[0].Volume
|
result.volume=res[0].Volume
|
||||||
result.profit=((result["当前价格"]-result.costPrice)*100/result.costPrice).toFixed(3)
|
result.profit=((result["当前价格"]-result.costPrice)*100/result.costPrice).toFixed(3)
|
||||||
@ -183,13 +203,24 @@ async function monitor() {
|
|||||||
}else if(result.profitAmount<0){
|
}else if(result.profitAmount<0){
|
||||||
result.profitType="success"
|
result.profitType="success"
|
||||||
}
|
}
|
||||||
|
if(Math.abs(res[0].AlarmChangePercent)>0&&roundedNum>res[0].AlarmChangePercent){
|
||||||
|
SendMessage(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
results.value[result["股票名称"]]=result
|
results.value[result["股票名称"]]=result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onSelect(item) {
|
function onSelect(item) {
|
||||||
data.code=item.split(".")[1].toLowerCase()+item.split(".")[0]
|
console.log("onSelect",item)
|
||||||
|
|
||||||
|
if(item.indexOf("-")>0){
|
||||||
|
item=item.split("-")[1].toLowerCase()
|
||||||
|
}
|
||||||
|
if(item.indexOf(".")>0){
|
||||||
|
data.code=item.split(".")[1].toLowerCase()+item.split(".")[0]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(code,name){
|
function search(code,name){
|
||||||
@ -204,6 +235,7 @@ function setStock(code,name){
|
|||||||
formModel.value.code=code
|
formModel.value.code=code
|
||||||
formModel.value.volume=res[0].Volume
|
formModel.value.volume=res[0].Volume
|
||||||
formModel.value.costPrice=res[0].CostPrice
|
formModel.value.costPrice=res[0].CostPrice
|
||||||
|
formModel.value.alarm=res[0].AlarmChangePercent
|
||||||
modalShow.value=true
|
modalShow.value=true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +253,13 @@ function showK(code,name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateCostPriceAndVolumeNew(code,price,volume){
|
function updateCostPriceAndVolumeNew(code,price,volume,alarm){
|
||||||
console.log(code,price,volume)
|
console.log(code,price,volume)
|
||||||
|
if(alarm){
|
||||||
|
SetAlarmChangePercent(alarm,code).then(result => {
|
||||||
|
//message.success(result)
|
||||||
|
})
|
||||||
|
}
|
||||||
SetCostPriceAndVolume(code,price,volume).then(result => {
|
SetCostPriceAndVolume(code,price,volume).then(result => {
|
||||||
modalShow.value=false
|
modalShow.value=false
|
||||||
message.success(result)
|
message.success(result)
|
||||||
@ -247,6 +284,33 @@ function fullscreen(){
|
|||||||
}
|
}
|
||||||
data.fullscreen=!data.fullscreen
|
data.fullscreen=!data.fullscreen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SendMessage(result){
|
||||||
|
let img='http://image.sinajs.cn/newchart/min/n/'+result["股票代码"]+'.gif'+"?t="+Date.now()
|
||||||
|
let markdown="### go-stock市场行情\n\n"+
|
||||||
|
"### "+result["股票名称"]+"("+result["股票代码"]+")\n" +
|
||||||
|
"- 当前价格: "+result["当前价格"]+" "+result.s+"\n" +
|
||||||
|
"- 最高价: "+result["今日最高价"]+" "+result.highRate+"\n" +
|
||||||
|
"- 最低价: "+result["今日最低价"]+" "+result.lowRate+"\n" +
|
||||||
|
"- 昨收价: "+result["昨日收盘价"]+"\n" +
|
||||||
|
"- 今开价: "+result["今日开盘价"]+"\n" +
|
||||||
|
"- 成本价: "+result.costPrice+" "+result.profit+"% "+result.profitAmount+" ¥\n" +
|
||||||
|
"- 成本数量: "+result.volume+"股\n" +
|
||||||
|
"- 日期: "+result["日期"]+" "+result["时间"]+"\n\n"+
|
||||||
|
"\n"
|
||||||
|
let msg='{' +
|
||||||
|
' "msgtype": "markdown",' +
|
||||||
|
' "markdown": {' +
|
||||||
|
' "title":"'+result["股票名称"]+"("+result["股票代码"]+") "+result["当前价格"]+" "+result.s+'",' +
|
||||||
|
' "text": "'+markdown+'"' +
|
||||||
|
' },' +
|
||||||
|
' "at": {' +
|
||||||
|
' "isAtAll": true' +
|
||||||
|
' }' +
|
||||||
|
' }'
|
||||||
|
SendDingDingMessage(msg,result["股票代码"])
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -289,7 +353,7 @@ function fullscreen(){
|
|||||||
<n-button size="tiny" type="success" @click="showFenshi(result['股票代码'],result['股票名称'])"> 分时 </n-button>
|
<n-button size="tiny" type="success" @click="showFenshi(result['股票代码'],result['股票名称'])"> 分时 </n-button>
|
||||||
<n-button size="tiny" type="error" @click="showK(result['股票代码'],result['股票名称'])"> 日K </n-button>
|
<n-button size="tiny" type="error" @click="showK(result['股票代码'],result['股票名称'])"> 日K </n-button>
|
||||||
<n-button size="tiny" type="warning" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
<n-button size="tiny" type="warning" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
||||||
|
<!-- <n-button size="tiny" type="info" @click="SendMessage(result)"> 钉钉 </n-button>-->
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
</n-card >
|
</n-card >
|
||||||
@ -305,8 +369,8 @@ function fullscreen(){
|
|||||||
autocomplete: 'disabled',
|
autocomplete: 'disabled',
|
||||||
}"
|
}"
|
||||||
:options="options"
|
:options="options"
|
||||||
placeholder="请输入股票名称或者代码"
|
placeholder="请输入股票/指数名称或者代码"
|
||||||
clearable @input="getStockList" :on-select="onSelect"/>
|
clearable @update-value="getStockList" :on-select="onSelect"/>
|
||||||
<n-button type="primary" @click="AddStock">
|
<n-button type="primary" @click="AddStock">
|
||||||
<n-icon :component="Add"/> 关注该股票
|
<n-icon :component="Add"/> 关注该股票
|
||||||
</n-button>
|
</n-button>
|
||||||
@ -315,16 +379,31 @@ function fullscreen(){
|
|||||||
|
|
||||||
</n-affix>
|
</n-affix>
|
||||||
<n-modal transform-origin="center" size="small" v-model:show="modalShow" :title="formModel.name" style="width: 400px" :preset="'card'">
|
<n-modal transform-origin="center" size="small" v-model:show="modalShow" :title="formModel.name" style="width: 400px" :preset="'card'">
|
||||||
<n-form :model="formModel" :rules="{ costPrice: { required: true, message: '请输入成本'}, volume: { required: true, message: '请输入数量'} }" label-placement="left" label-width="80px">
|
<n-form :model="formModel" :rules="{ costPrice: { required: true, message: '请输入成本'}, volume: { required: true, message: '请输入数量'},alarm:{required: true, message: '涨跌报警值'} }" label-placement="left" label-width="80px">
|
||||||
<n-form-item label="成本(元)" path="costPrice">
|
<n-form-item label="股票成本" path="costPrice">
|
||||||
<n-input-number v-model:value="formModel.costPrice" min="0" placeholder="请输入股票成本" />
|
<n-input-number v-model:value="formModel.costPrice" min="0" placeholder="请输入股票成本" >
|
||||||
|
<template #suffix>
|
||||||
|
元
|
||||||
|
</template>
|
||||||
|
</n-input-number>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item label="数量(股)" path="volume">
|
<n-form-item label="股票数量" path="volume">
|
||||||
<n-input-number v-model:value="formModel.volume" min="0" placeholder="请输入股票数量" />
|
<n-input-number v-model:value="formModel.volume" min="0" step="100" placeholder="请输入股票数量" >
|
||||||
|
<template #suffix>
|
||||||
|
股
|
||||||
|
</template>
|
||||||
|
</n-input-number>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="涨跌提醒" path="alarm">
|
||||||
|
<n-input-number v-model:value="formModel.alarm" min="0" placeholder="请输入涨跌报警值(%)" >
|
||||||
|
<template #suffix>
|
||||||
|
%
|
||||||
|
</template>
|
||||||
|
</n-input-number>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-button type="primary" @click="updateCostPriceAndVolumeNew(formModel.code,formModel.costPrice,formModel.volume)">保存</n-button>
|
<n-button type="primary" @click="updateCostPriceAndVolumeNew(formModel.code,formModel.costPrice,formModel.volume,formModel.alarm)">保存</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
|
||||||
|
4
frontend/wailsjs/go/main/App.d.ts
vendored
4
frontend/wailsjs/go/main/App.d.ts
vendored
@ -10,6 +10,10 @@ export function GetStockList(arg1:string):Promise<Array<data.StockBasic>>;
|
|||||||
|
|
||||||
export function Greet(arg1:string):Promise<data.StockInfo>;
|
export function Greet(arg1:string):Promise<data.StockInfo>;
|
||||||
|
|
||||||
|
export function SendDingDingMessage(arg1:string,arg2:string):Promise<string>;
|
||||||
|
|
||||||
|
export function SetAlarmChangePercent(arg1:number,arg2:string):Promise<string>;
|
||||||
|
|
||||||
export function SetCostPriceAndVolume(arg1:string,arg2:number,arg3:number):Promise<string>;
|
export function SetCostPriceAndVolume(arg1:string,arg2:number,arg3:number):Promise<string>;
|
||||||
|
|
||||||
export function UnFollow(arg1:string):Promise<string>;
|
export function UnFollow(arg1:string):Promise<string>;
|
||||||
|
@ -18,6 +18,14 @@ export function Greet(arg1) {
|
|||||||
return window['go']['main']['App']['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) {
|
export function SetCostPriceAndVolume(arg1, arg2, arg3) {
|
||||||
return window['go']['main']['App']['SetCostPriceAndVolume'](arg1, arg2, arg3);
|
return window['go']['main']['App']['SetCostPriceAndVolume'](arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ export namespace data {
|
|||||||
Price: number;
|
Price: number;
|
||||||
PriceChange: number;
|
PriceChange: number;
|
||||||
ChangePercent: number;
|
ChangePercent: number;
|
||||||
|
AlarmChangePercent: number;
|
||||||
// Go type: time
|
// Go type: time
|
||||||
Time: any;
|
Time: any;
|
||||||
Sort: number;
|
Sort: number;
|
||||||
@ -26,6 +27,7 @@ export namespace data {
|
|||||||
this.Price = source["Price"];
|
this.Price = source["Price"];
|
||||||
this.PriceChange = source["PriceChange"];
|
this.PriceChange = source["PriceChange"];
|
||||||
this.ChangePercent = source["ChangePercent"];
|
this.ChangePercent = source["ChangePercent"];
|
||||||
|
this.AlarmChangePercent = source["AlarmChangePercent"];
|
||||||
this.Time = this.convertValues(source["Time"], null);
|
this.Time = this.convertValues(source["Time"], null);
|
||||||
this.Sort = source["Sort"];
|
this.Sort = source["Sort"];
|
||||||
this.IsDel = source["IsDel"];
|
this.IsDel = source["IsDel"];
|
||||||
|
11
go.mod
11
go.mod
@ -5,7 +5,9 @@ go 1.21
|
|||||||
toolchain go1.23.0
|
toolchain go1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/coocood/freecache v1.2.4
|
||||||
github.com/duke-git/lancet/v2 v2.3.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/glebarez/sqlite v1.11.0
|
||||||
github.com/go-resty/resty/v2 v2.16.2
|
github.com/go-resty/resty/v2 v2.16.2
|
||||||
github.com/wailsapp/wails/v2 v2.9.2
|
github.com/wailsapp/wails/v2 v2.9.2
|
||||||
@ -19,9 +21,17 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bep/debounce v1.2.1 // indirect
|
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/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/glebarez/go-sqlite v1.21.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // 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/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // 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/leaanthony/u v1.1.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // 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/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
29
go.sum
29
go.sum
@ -1,5 +1,9 @@
|
|||||||
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
|
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
|
||||||
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/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 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
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 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
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-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 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
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 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
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/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 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI=
|
||||||
github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
|
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 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
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.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 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
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 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
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/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 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
||||||
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
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/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.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 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
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-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-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-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-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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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-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-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.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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.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=
|
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
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=
|
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/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 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
|
9
main.go
9
main.go
@ -25,6 +25,9 @@ var assets embed.FS
|
|||||||
//go:embed build/appicon.png
|
//go:embed build/appicon.png
|
||||||
var icon []byte
|
var icon []byte
|
||||||
|
|
||||||
|
//go:embed build/app.ico
|
||||||
|
var icon2 []byte
|
||||||
|
|
||||||
//go:embed build/stock_basic.json
|
//go:embed build/stock_basic.json
|
||||||
var stocksBin []byte
|
var stocksBin []byte
|
||||||
|
|
||||||
@ -35,11 +38,13 @@ func main() {
|
|||||||
db.Dao.AutoMigrate(&data.StockInfo{})
|
db.Dao.AutoMigrate(&data.StockInfo{})
|
||||||
db.Dao.AutoMigrate(&data.StockBasic{})
|
db.Dao.AutoMigrate(&data.StockBasic{})
|
||||||
db.Dao.AutoMigrate(&data.FollowedStock{})
|
db.Dao.AutoMigrate(&data.FollowedStock{})
|
||||||
|
db.Dao.AutoMigrate(&data.IndexBasic{})
|
||||||
|
|
||||||
if stocksBin != nil && len(stocksBin) > 0 {
|
if stocksBin != nil && len(stocksBin) > 0 {
|
||||||
go initStockData()
|
go initStockData()
|
||||||
}
|
}
|
||||||
go data.NewStockDataApi().GetStockBaseInfo()
|
go data.NewStockDataApi().GetStockBaseInfo()
|
||||||
|
go data.NewStockDataApi().GetIndexBasic()
|
||||||
|
|
||||||
// Create an instance of the app structure
|
// Create an instance of the app structure
|
||||||
app := NewApp()
|
app := NewApp()
|
||||||
@ -63,9 +68,13 @@ func main() {
|
|||||||
FileMenu.AddText("窗口还原", keys.Key("Esc"), func(callback *menu.CallbackData) {
|
FileMenu.AddText("窗口还原", keys.Key("Esc"), func(callback *menu.CallbackData) {
|
||||||
runtime.WindowUnfullscreen(app.ctx)
|
runtime.WindowUnfullscreen(app.ctx)
|
||||||
})
|
})
|
||||||
|
FileMenu.AddText("隐藏到托盘区", keys.CmdOrCtrl("h"), func(_ *menu.CallbackData) {
|
||||||
|
runtime.Hide(app.ctx)
|
||||||
|
})
|
||||||
FileMenu.AddText("退出", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
|
FileMenu.AddText("退出", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
|
||||||
runtime.Quit(app.ctx)
|
runtime.Quit(app.ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create application with options
|
// Create application with options
|
||||||
err := wails.Run(&options.App{
|
err := wails.Run(&options.App{
|
||||||
Title: "go-stock",
|
Title: "go-stock",
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{"request_id":"bf5b7774-d16d-43fe-9806-dff9ef37cd33","code":40203,"data":null,"msg":"抱歉,您每小时最多访问该接口1次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。"}
|
|
Loading…
x
Reference in New Issue
Block a user