mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
Compare commits
10 Commits
v2025.6.25
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
6116e9287a | ||
|
3e16574faa | ||
|
482472af4e | ||
|
bdc3689ac8 | ||
|
e8ebb577b2 | ||
|
71f8265bc2 | ||
|
43063fa7fb | ||
|
86f041b4d6 | ||
|
0ce7e8e7a7 | ||
|
bbab60e2ad |
21
README.md
21
README.md
@ -26,16 +26,17 @@
|
|||||||
|
|
||||||
|
|
||||||
### 💬 支持大模型/平台
|
### 💬 支持大模型/平台
|
||||||
| 模型 | 状态 | 备注 |
|
| 模型 | 状态 | 备注 |
|
||||||
| --- | --- |-----------------------------------------------------------------------------------------------------------------------------------------------------|
|
| --- | --- |---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| [OpenAI](https://platform.openai.com/) | ✅ | 可接入任何 OpenAI 接口格式模型 |
|
| [OpenAI](https://platform.openai.com/) | ✅ | 可接入任何 OpenAI 接口格式模型 |
|
||||||
| [Ollama](https://ollama.com/) | ✅ | 本地大模型运行平台 |
|
| [Ollama](https://ollama.com/) | ✅ | 本地大模型运行平台 |
|
||||||
| [LMStudio](https://lmstudio.ai/) | ✅ | 本地大模型运行平台 |
|
| [LMStudio](https://lmstudio.ai/) | ✅ | 本地大模型运行平台 |
|
||||||
| [AnythingLLM](https://anythingllm.com/) | ✅ | 本地知识库 |
|
| [AnythingLLM](https://anythingllm.com/) | ✅ | 本地知识库 |
|
||||||
| [DeepSeek](https://www.deepseek.com/) | ✅ | deepseek-reasoner,deepseek-chat |
|
| [DeepSeek](https://www.deepseek.com/) | ✅ | deepseek-reasoner,deepseek-chat |
|
||||||
| [大模型聚合平台](https://cloud.siliconflow.cn/i/foufCerk) | ✅ | 如:[硅基流动](https://cloud.siliconflow.cn/i/foufCerk),[火山方舟](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ) |
|
| [大模型聚合平台](https://cloud.siliconflow.cn/i/foufCerk) | ✅ | 如:[硅基流动](https://cloud.siliconflow.cn/i/foufCerk),[火山方舟](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ) ,[优云智算](https://www.compshare.cn/image-community?ytag=GPU_YY-gh_gostock) |
|
||||||
|
|
||||||
### <span style="color: #568DF4;">各位亲爱的朋友们,如果您对这个项目感兴趣,请先给我一个<i style="color: #EA2626;">star</i>吧,谢谢!</span>💕
|
### <span style="color: #568DF4;">各位亲爱的朋友们,如果您对这个项目感兴趣,请先给我一个<i style="color: #EA2626;">star</i>吧,谢谢!</span>💕
|
||||||
|
- 优云智算(by UCloud):万卡规模4090免费用10小时,新人注册另增50万tokens,海量热门源项目镜像一键部署,[注册链接](https://www.compshare.cn/image-community?ytag=GPU_YY-gh_gostock)
|
||||||
- 经测试目前硅基流动(siliconflow)提供的deepSeek api 服务比较稳定,注册即送2000万Tokens,[注册链接](https://cloud.siliconflow.cn/i/foufCerk)
|
- 经测试目前硅基流动(siliconflow)提供的deepSeek api 服务比较稳定,注册即送2000万Tokens,[注册链接](https://cloud.siliconflow.cn/i/foufCerk)
|
||||||
- 火山方舟:每个模型注册即送50万tokens,[注册链接](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ)
|
- 火山方舟:每个模型注册即送50万tokens,[注册链接](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ)
|
||||||
- Tushare大数据开放社区,免费提供各类金融数据,助力行业和量化研究(注意:Tushare只需要120积分即可,注册完成个人资料补充即可得120积分!!!),[注册链接](https://tushare.pro/register?reg=701944)
|
- Tushare大数据开放社区,免费提供各类金融数据,助力行业和量化研究(注意:Tushare只需要120积分即可,注册完成个人资料补充即可得120积分!!!),[注册链接](https://tushare.pro/register?reg=701944)
|
||||||
@ -46,6 +47,8 @@
|
|||||||
## 🧩 重大功能开发计划
|
## 🧩 重大功能开发计划
|
||||||
| 功能说明 | 状态 | 备注 |
|
| 功能说明 | 状态 | 备注 |
|
||||||
|-----------------|----|----------------------------------------------------------------------------------------------------------|
|
|-----------------|----|----------------------------------------------------------------------------------------------------------|
|
||||||
|
| 股票分析知识库 | 🚧 | 未来计划 |
|
||||||
|
| Ai智能选股 | 🚧 | Ai智能选股功能开发中(下半年重点开发计划) |
|
||||||
| ETF支持 | 🚧 | ETF数据支持 (目前可以查看净值和估值) |
|
| ETF支持 | 🚧 | ETF数据支持 (目前可以查看净值和估值) |
|
||||||
| 美股支持 | ✅ | 美股数据支持 |
|
| 美股支持 | ✅ | 美股数据支持 |
|
||||||
| 港股支持 | ✅ | 港股数据支持 |
|
| 港股支持 | ✅ | 港股数据支持 |
|
||||||
@ -54,6 +57,8 @@
|
|||||||
| 不再强制依赖Chrome浏览器 | ✅ | 默认使用edge浏览器抓取新闻资讯 |
|
| 不再强制依赖Chrome浏览器 | ✅ | 默认使用edge浏览器抓取新闻资讯 |
|
||||||
|
|
||||||
## 👀 更新日志
|
## 👀 更新日志
|
||||||
|
### 2025.06.30 添加指标选股功能
|
||||||
|
### 2025.06.27 添加财经日历和重大事件时间轴功能
|
||||||
### 2025.06.25 添加热门股票、事件和话题功能
|
### 2025.06.25 添加热门股票、事件和话题功能
|
||||||
### 2025.06.18 更新内置股票基础数据,软件内实时市场资讯信息提醒,添加行业研究功能
|
### 2025.06.18 更新内置股票基础数据,软件内实时市场资讯信息提醒,添加行业研究功能
|
||||||
### 2025.06.15 添加公司公告信息搜索/查看功能
|
### 2025.06.15 添加公司公告信息搜索/查看功能
|
||||||
|
@ -48,3 +48,14 @@ func (a App) HotTopic(size int) []any {
|
|||||||
}
|
}
|
||||||
return data.NewMarketNewsApi().HotTopic(size)
|
return data.NewMarketNewsApi().HotTopic(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a App) InvestCalendarTimeLine(yearMonth string) []any {
|
||||||
|
return data.NewMarketNewsApi().InvestCalendar(yearMonth)
|
||||||
|
}
|
||||||
|
func (a App) ClsCalendar() []any {
|
||||||
|
return data.NewMarketNewsApi().ClsCalendar()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a App) SearchStock(words string) map[string]any {
|
||||||
|
return data.NewSearchStockApi(words).SearchStock()
|
||||||
|
}
|
||||||
|
@ -576,21 +576,30 @@ func (m MarketNewsApi) TradingViewNews() *[]models.TVNews {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m MarketNewsApi) XUEQIUHotStock(size int, marketType string) *[]models.HotItem {
|
func (m MarketNewsApi) XUEQIUHotStock(size int, marketType string) *[]models.HotItem {
|
||||||
|
request := resty.New().SetTimeout(time.Duration(30) * time.Second).R()
|
||||||
|
_, err := request.
|
||||||
|
SetHeader("Host", "xueqiu.com").
|
||||||
|
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
||||||
|
Get("https://xueqiu.com/hq#hot")
|
||||||
|
|
||||||
|
//cookies := resp.Header().Get("Set-Cookie")
|
||||||
|
//logger.SugaredLogger.Infof("cookies:%s", cookies)
|
||||||
|
|
||||||
url := fmt.Sprintf("https://stock.xueqiu.com/v5/stock/hot_stock/list.json?page=1&size=%d&_type=%s&type=%s", size, marketType, marketType)
|
url := fmt.Sprintf("https://stock.xueqiu.com/v5/stock/hot_stock/list.json?page=1&size=%d&_type=%s&type=%s", size, marketType, marketType)
|
||||||
res := &models.XUEQIUHot{}
|
res := &models.XUEQIUHot{}
|
||||||
_, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
_, err = request.
|
||||||
SetHeader("Host", "stock.xueqiu.com").
|
SetHeader("Host", "stock.xueqiu.com").
|
||||||
SetHeader("Origin", "https://xueqiu.com").
|
SetHeader("Origin", "https://xueqiu.com").
|
||||||
SetHeader("Referer", "https://xueqiu.com/").
|
SetHeader("Referer", "https://xueqiu.com/").
|
||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
||||||
SetHeader("Cookie", "cookiesu=2617378771242871; s=c2121pp1u71; device_id=237a58584ec58d8e4d4e1040700a644f1; Hm_lvt_1db88642e346389874251b5a1eded6e3=1744100219,1744599115; xq_a_token=b7259d09435458cc3f1a963479abb270a1a016ce; xqat=b7259d09435458cc3f1a963479abb270a1a016ce; xq_r_token=28108bfa1d92ac8a46bbb57722633746218621a3; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOi0xLCJpc3MiOiJ1YyIsImV4cCI6MTc1MjU0MTk4OCwiY3RtIjoxNzUwMjMwNjA2NzI0LCJjaWQiOiJkOWQwbjRBWnVwIn0.kU_fz0luJoE7nr-K4UrNUi5-mAG-vMdXtuC4mUKIppILId4UpF70LB70yunxGiNSw6tPFR3-hyLvztKAHtekCUTm3XjUl5b3tEDP-ZUVqHnWXO_5hoeMI8h-Cfx6ZGlIr5x3icvTPkT0OV5CD5A33-ZDTKhKPf-DhJ_-m7CG5GbX4MseOBeMXuLUQUiYHPKhX1QUc0GTGrCzi8Mki0z49D0LVqCSgbsx3UGfowOOyx85_cXb4OAFvIjwbs2p0o_h-ibIT0ngVkkAyEDetVvlcZ_bkardhseCB7k9BEMgH2z8ihgkVxyy3P0degLmDUruhmqn5uZOCi1pVBDvCv9lBg; u=261737877124287; ssxmod_itna=QuG=D5AKiKDIqCqGKi7G7DgmmPlSDWFqKGHDyx4YK0CDmxjKiddDUQivnb8xpnQcGyGYoYhoqEeDBubrDSxD67DK4GTm+ogiw1o3B=xedQHDgBtN=7/i1K53N+rOjquLMU=kbqYxB3DExGkqj0tPi4DxaPD5xDTDWeDGDD3DnnsDQKDRx0kL0oDIxD1D0bmHUEvh38mDYePLmOmDYPYx94Y8KoDeEgsD7HUl/vIGGEAqjLPFegXLD0HolCqr4DCid1qDm+ECfkjDn9sD0KP8fn+CRoDv=tYr4ibx+o=W+8vstf9mjGe3cXseWdBmoFrmf4DA3bFAxnAxD7vYxADaDoerDGHPoxHF+PKGPtDKmiqQGeB5qbi4eg4KDHKDe3DeG0qeEP9xVUoHDDWMYYM0ICr4FBimBDM7D0x4QOECmhul5QCN/m5/74lGm=7x9Wp7A+i7xQ7wlMD4D; ssxmod_itna2=QuG=D5AKiKDIqCqGKi7G7DgmmPlSDWFqKGHDyx4YK0CDmxjKiddDUQivnb8xpnQcGyGYoYhoqoDirSDhPmGD24GajjDuGE3m7or4DlxOSGewHl6iaus2Q62SRX5CFjCds6ltF9xy6iaUuB262UkhRA8UXST=4/b+y3kGKzlGE8T29FA008ljy9jXXC7f7m7QsK667mlUooWrofk=qGZjxtcUrN1NtuAnne1hj+rQP5UnlFkxf+o7VjmatH7u7bCDlbTt3cz6CH9Fl4vye16W/ellc8I3Q37W7ZwiLGD/zPpZcnd2nsqqo/+zRbKAmz4plzwaDqGUe7f9E+P0IFRKqpRv+buQFHBSpcbwND7Q+9XWmnjI2UwKd98jIS3gPXwxvbx4OuiyH8gZ+OEt7DgE/AY/9W4VxDZrlFWyWnC4y4/I0IpAfaGKpbPmauKbkqawqv93vSf+9HamGe0Dt2PNgT3yiEB4vQP2/DdVpcGBOjFujWoHP32OshLPYI20LRCKddwEGkKqPzPwKPc3X5zuB=w2fUdtwKsAW5kQtsl8clNwjC5uDYrxR0h9xaj0xmD+YuI3GPT7xYTalRImPj2wL2=+91a304xa4bTWtP=dLGARhb/efRi0uktaz8i8C04G0x/ZWUzqRza8GGU=FfRfvb4GZM/q2rVsl0nLvRjGeAKgocLouyXs/uwZu3YxbAx30qCbjG1A533zAxIeIgD=0VAc3ixD").
|
//SetHeader("Cookie", "cookiesu=871730774144180; device_id=ee75cebba8a35005c9e7baf7b7dead59; s=ch12b12pfi; Hm_lvt_1db88642e346389874251b5a1eded6e3=1746247619; xq_a_token=361dcfccb1d32a1d9b5b65f1a188b9c9ed1e687d; xqat=361dcfccb1d32a1d9b5b65f1a188b9c9ed1e687d; xq_r_token=450d1db0db9659a6af7cc9297bfa4fccf1776fae; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOi0xLCJpc3MiOiJ1YyIsImV4cCI6MTc1MzgzODAwNiwiY3RtIjoxNzUxMjUxMzc2MDY3LCJjaWQiOiJkOWQwbjRBWnVwIn0.TjEtQ5WEN4ajnVjVnY3J-Qq9LjL-F0eat9Cefv_tLJLqsPhzD2y8Lc1CeIu0Ceqhlad7O_yW1tR9nb2dIjDpyOPzWKxvwSOKXLm8XMoz4LMgE2pysBCH4TsetzHsEOhBsY467q-JX3WoFuqo-dqv1FfLSondZCspjEMFdgPFt2V-2iXJY05YUwcBVUvL74mT9ZjNq0KaDeRBJk_il6UR8yibG7RMbe9xWYz5dSO_wJwWuxvnZ8u9EXC2m-TV7-QHVxFHR_5e8Fodrzg0yIcLU4wBTSoIIQDUKqngajX2W-nUAdo6fr78NNDmoswFVH7T7XMuQciMAqj9MpMCVW3Sog; u=871730774144180; ssxmod_itna=iq+h7KAImDORKYQ4Y5G=nxBKDtD7D3qCD0dGMDxeq7tDRDFqApKDHtA68oon7ziBA0+PbZ9xGN4oYxiNDAPq0iDC+Wjxs9Orw5KQb9iqP4MAn0TbNsbtU22eqbCe=S3vTv6xoDHxY=DU1GzeieDx=PD5xDTDWeDGDD3DmnsDi5YD0KDjBYpH+omDYPDEBYDaxDbDimwY4GCrDDCtc5Dw6bmzDDzznL5WWAPzWffZg3YcFgxf8GwD7y3Dla4rMhw23=cz0Efdk0A5hYDXotDvhoY1/H6neEvOt3o=Q0ruT+5RuxoRhDxCmh5tGP32xBD5G0xS2xcb4quDK0Dy2ZmY/DDWM0qmEeSEDeOCIq1fw1misCY=WAzoOtMwDzGdUjpRk5Z0xQBDI2IMw4H7qNiNBLxWiDD; ssxmod_itna2=iq+h7KAImDORKYQ4Y5G=nxBKDtD7D3qCD0dGMDxeq7tDRDFqApKDHtA68oon7ziBA0+PbZYxD3boBmiEPtDFOEPAeFmDDsuGSxf46oGKwGHd8wtUjFe+oV1lxUzutkGly=nCyCjq=UTHxMxFCr1DsFiKPuEpPVO7GrOyk5Aymnc0+11AFND7v16PvwrFQH4I72=3O1OpK7rGw+poWNCxjj=Ka5QDFWAvEzrDFQcIH=GpKpS90FAyIzGcTyck+yhQKaojn96dRqeIh=HkaFrlGnKwzO+a49=F7/c/MejoR3QM20K9IIOymrMN2bsk2TRdKFiaf4O0ut2MauiOER=iQNW2WVgDrkKzD=57r577wEx2hwkqhf8T8BDvkHZRDirC0bNK4O=G3TSkd3wYwq8bst0t9qF/e3M87NYtU2IWYWzqd=BqEfdqGq0R8wxmqLzpeGeuwSTq1OAiB87gDrozjnGkwDKRdrLz8uDjQKVlGhWk8Wd/rXQjx4pG=BNqpW/6TS1wpfxzGf5CrUhtt0j0wC5AUFo2GbX+QXPzD2guxKXrx8lZUQlwWIHyEUz+OLh0eWUkfHfM0YWXlgOejnuUa06rW9y5maDPipGms751hxKcqLq62pQty4iX3QDF6SRQd3tfEBf3CH7r2xe2qq0qdOI5Ge=GezD/Us5Z0xQBwVAZ2N/XvD0HDD").
|
||||||
SetResult(res).
|
SetResult(res).
|
||||||
Get(url)
|
Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.SugaredLogger.Errorf("XUEQIUHotStock err:%s", err.Error())
|
logger.SugaredLogger.Errorf("XUEQIUHotStock err:%s", err.Error())
|
||||||
return &[]models.HotItem{}
|
return &[]models.HotItem{}
|
||||||
}
|
}
|
||||||
// logger.SugaredLogger.Infof("XUEQIUHotStock:%+v", res)
|
logger.SugaredLogger.Infof("XUEQIUHotStock:%+v", res)
|
||||||
return &res.Data.Items
|
return &res.Data.Items
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,3 +652,52 @@ func (m MarketNewsApi) HotTopic(size int) []any {
|
|||||||
return respMap["re"].([]any)
|
return respMap["re"].([]any)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m MarketNewsApi) InvestCalendar(yearMonth string) []any {
|
||||||
|
if yearMonth == "" {
|
||||||
|
yearMonth = time.Now().Format("2006-01")
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "https://app.jiuyangongshe.com/jystock-app/api/v1/timeline/list"
|
||||||
|
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
||||||
|
SetHeader("Host", "app.jiuyangongshe.com").
|
||||||
|
SetHeader("Origin", "https://www.jiuyangongshe.com").
|
||||||
|
SetHeader("Referer", "https://www.jiuyangongshe.com/").
|
||||||
|
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
||||||
|
SetHeader("Content-Type", "application/json").
|
||||||
|
SetHeader("token", "1cc6380a05c652b922b3d85124c85473").
|
||||||
|
SetHeader("platform", "3").
|
||||||
|
SetHeader("Cookie", "SESSION=NDZkNDU2ODYtODEwYi00ZGZkLWEyY2ItNjgxYzY4ZWMzZDEy").
|
||||||
|
SetHeader("timestamp", strconv.FormatInt(time.Now().UnixMilli(), 10)).
|
||||||
|
SetBody(map[string]string{
|
||||||
|
"date": yearMonth,
|
||||||
|
"grade": "0",
|
||||||
|
}).
|
||||||
|
Post(url)
|
||||||
|
if err != nil {
|
||||||
|
logger.SugaredLogger.Errorf("InvestCalendar err:%s", err.Error())
|
||||||
|
return []any{}
|
||||||
|
}
|
||||||
|
//logger.SugaredLogger.Infof("InvestCalendar:%s", resp.Body())
|
||||||
|
respMap := map[string]any{}
|
||||||
|
err = json.Unmarshal(resp.Body(), &respMap)
|
||||||
|
return respMap["data"].([]any)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MarketNewsApi) ClsCalendar() []any {
|
||||||
|
url := "https://www.cls.cn/api/calendar/web/list?app=CailianpressWeb&flag=0&os=web&sv=8.4.6&type=0&sign=4b839750dc2f6b803d1c8ca00d2b40be"
|
||||||
|
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
||||||
|
SetHeader("Host", "www.cls.cn").
|
||||||
|
SetHeader("Origin", "https://www.cls.cn").
|
||||||
|
SetHeader("Referer", "https://www.cls.cn/").
|
||||||
|
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
||||||
|
Get(url)
|
||||||
|
if err != nil {
|
||||||
|
logger.SugaredLogger.Errorf("ClsCalendar err:%s", err.Error())
|
||||||
|
return []any{}
|
||||||
|
}
|
||||||
|
respMap := map[string]any{}
|
||||||
|
err = json.Unmarshal(resp.Body(), &respMap)
|
||||||
|
return respMap["data"].([]any)
|
||||||
|
}
|
||||||
|
@ -135,3 +135,19 @@ func TestHotTopic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInvestCalendar(t *testing.T) {
|
||||||
|
db.Init("../../data/stock.db")
|
||||||
|
res := NewMarketNewsApi().InvestCalendar("2025-06")
|
||||||
|
for _, a := range res {
|
||||||
|
logger.SugaredLogger.Debugf("value: %+v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClsCalendar(t *testing.T) {
|
||||||
|
db.Init("../../data/stock.db")
|
||||||
|
res := NewMarketNewsApi().ClsCalendar()
|
||||||
|
for _, a := range res {
|
||||||
|
logger.SugaredLogger.Debugf("value: %+v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
55
backend/data/search_stock_api.go
Normal file
55
backend/data/search_stock_api.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
"go-stock/backend/logger"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Author spark
|
||||||
|
// @Date 2025/6/28 21:02
|
||||||
|
// @Desc
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
|
type SearchStockApi struct {
|
||||||
|
words string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearchStockApi(words string) *SearchStockApi {
|
||||||
|
return &SearchStockApi{words: words}
|
||||||
|
}
|
||||||
|
func (s SearchStockApi) SearchStock() map[string]any {
|
||||||
|
url := "https://np-tjxg-g.eastmoney.com/api/smart-tag/stock/v3/pw/search-code"
|
||||||
|
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
||||||
|
SetHeader("Host", "np-tjxg-g.eastmoney.com").
|
||||||
|
SetHeader("Origin", "https://xuangu.eastmoney.com").
|
||||||
|
SetHeader("Referer", "https://xuangu.eastmoney.com/").
|
||||||
|
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
||||||
|
SetHeader("Content-Type", "application/json").
|
||||||
|
SetBody(fmt.Sprintf(`{
|
||||||
|
"keyWord": "%s",
|
||||||
|
"pageSize": 50000,
|
||||||
|
"pageNo": 1,
|
||||||
|
"fingerprint": "e38b5faabf9378c8238e57219f0ebc9b",
|
||||||
|
"gids": [],
|
||||||
|
"matchWord": "",
|
||||||
|
"timestamp": "1751113883290349",
|
||||||
|
"shareToGuba": false,
|
||||||
|
"requestId": "8xTWgCDAjvQ5lmvz5mDA3Ydk2AE4yoiJ1751113883290",
|
||||||
|
"needCorrect": true,
|
||||||
|
"removedConditionIdList": [],
|
||||||
|
"xcId": "xc0af28549ab330013ed",
|
||||||
|
"ownSelectAll": false,
|
||||||
|
"dxInfo": [],
|
||||||
|
"extraCondition": ""
|
||||||
|
}`, s.words)).Post(url)
|
||||||
|
if err != nil {
|
||||||
|
logger.SugaredLogger.Errorf("SearchStock-err:%+v", err)
|
||||||
|
return map[string]any{}
|
||||||
|
}
|
||||||
|
respMap := map[string]any{}
|
||||||
|
json.Unmarshal(resp.Body(), &respMap)
|
||||||
|
//logger.SugaredLogger.Infof("resp:%+v", respMap["data"])
|
||||||
|
return respMap
|
||||||
|
}
|
25
backend/data/search_stock_api_test.go
Normal file
25
backend/data/search_stock_api_test.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-stock/backend/db"
|
||||||
|
"go-stock/backend/logger"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSearchStock(t *testing.T) {
|
||||||
|
db.Init("../../data/stock.db")
|
||||||
|
|
||||||
|
res := NewSearchStockApi("算力股;净利润连续3年增长").SearchStock()
|
||||||
|
data := res["data"].(map[string]any)
|
||||||
|
result := data["result"].(map[string]any)
|
||||||
|
dataList := result["dataList"].([]any)
|
||||||
|
for _, v := range dataList {
|
||||||
|
d := v.(map[string]any)
|
||||||
|
logger.SugaredLogger.Infof("%s:%s", d["INDUSTRY"], d["SECURITY_SHORT_NAME"])
|
||||||
|
}
|
||||||
|
//columns := result["columns"].([]any)
|
||||||
|
//for _, v := range columns {
|
||||||
|
// logger.SugaredLogger.Infof("v:%+v", v)
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
@ -406,6 +406,13 @@ func (receiver StockDataApi) Follow(stockCode string) string {
|
|||||||
if strings.HasPrefix(stockCode, "US") {
|
if strings.HasPrefix(stockCode, "US") {
|
||||||
stockCode = strings.Replace(stockCode, "US", "gb_", 1)
|
stockCode = strings.Replace(stockCode, "US", "gb_", 1)
|
||||||
}
|
}
|
||||||
|
count := int64(0)
|
||||||
|
db.Dao.Model(&FollowedStock{}).Where("is_del = ?", 0).Count(&count)
|
||||||
|
logger.SugaredLogger.Errorf("Follow-count %v", count)
|
||||||
|
if count >= 63 {
|
||||||
|
return "最多只能关注63只股票"
|
||||||
|
}
|
||||||
|
|
||||||
stockCode = strings.ToLower(stockCode)
|
stockCode = strings.ToLower(stockCode)
|
||||||
maxSort := int64(0)
|
maxSort := int64(0)
|
||||||
db.Dao.Model(&FollowedStock{}).Raw("select max(sort) as sort from followed_stock").Scan(&maxSort)
|
db.Dao.Model(&FollowedStock{}).Raw("select max(sort) as sort from followed_stock").Scan(&maxSort)
|
||||||
|
20
frontend/package-lock.json
generated
20
frontend/package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@vavt/cm-extension": "^1.8.0",
|
"@vavt/cm-extension": "^1.8.0",
|
||||||
"@vavt/v3-extension": "^3.0.0",
|
"@vavt/v3-extension": "^3.0.0",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
@ -1717,10 +1718,10 @@
|
|||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
},
|
},
|
||||||
"node_modules/date-fns": {
|
"node_modules/date-fns": {
|
||||||
"version": "3.6.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-3.6.0.tgz",
|
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-4.1.0.tgz",
|
||||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||||
"dev": true,
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/kossnocorp"
|
"url": "https://github.com/sponsors/kossnocorp"
|
||||||
@ -2066,6 +2067,17 @@
|
|||||||
"vue": "^3.0.0"
|
"vue": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/naive-ui/node_modules/date-fns": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/kossnocorp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@vavt/cm-extension": "^1.8.0",
|
"@vavt/cm-extension": "^1.8.0",
|
||||||
"@vavt/v3-extension": "^3.0.0",
|
"@vavt/v3-extension": "^3.0.0",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
|
@ -1 +1 @@
|
|||||||
f64f2faecc1cae8baa43eca694be54ac
|
2d63c3a999d797889c01d6c96451b197
|
@ -31,7 +31,7 @@ import {AnalyzeSentiment, GetConfig, GetGroupList} from "../wailsjs/go/main/App"
|
|||||||
import {Dragon, Fire, Gripfire} from "@vicons/fa";
|
import {Dragon, Fire, Gripfire} from "@vicons/fa";
|
||||||
import {ReportSearch} from "@vicons/tabler";
|
import {ReportSearch} from "@vicons/tabler";
|
||||||
import {LocalFireDepartmentRound} from "@vicons/material";
|
import {LocalFireDepartmentRound} from "@vicons/material";
|
||||||
import {CommentNote20Filled} from "@vicons/fluent";
|
import {BoxSearch20Regular, CommentNote20Filled} from "@vicons/fluent";
|
||||||
import {FireFilled, FireOutlined, NotificationFilled, StockOutlined} from "@vicons/antd";
|
import {FireFilled, FireOutlined, NotificationFilled, StockOutlined} from "@vicons/antd";
|
||||||
|
|
||||||
|
|
||||||
@ -332,6 +332,27 @@ const menuOptions = ref([
|
|||||||
key: 'market10',
|
key: 'market10',
|
||||||
icon: renderIcon(Gripfire),
|
icon: renderIcon(Gripfire),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{
|
||||||
|
href: '#',
|
||||||
|
to: {
|
||||||
|
name: 'market',
|
||||||
|
query: {
|
||||||
|
name: "指标选股",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
EventsEmit("changeMarketTab", {ID: 0, name: '指标选股'})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{default: () => '指标选股',}
|
||||||
|
),
|
||||||
|
key: 'market11',
|
||||||
|
icon: renderIcon(BoxSearch20Regular),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
102
frontend/src/components/ClsCalendarTimeLine.vue
Normal file
102
frontend/src/components/ClsCalendarTimeLine.vue
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {nextTick, onBeforeMount, onMounted, onUnmounted, ref} from 'vue'
|
||||||
|
import {ClsCalendar} from "../../wailsjs/go/main/App";
|
||||||
|
import { addMonths, format ,parse} from 'date-fns';
|
||||||
|
import { zhCN } from 'date-fns/locale';
|
||||||
|
|
||||||
|
import {useMessage} from 'naive-ui'
|
||||||
|
import {Star48Filled} from "@vicons/fluent";
|
||||||
|
const today = new Date();
|
||||||
|
const year = today.getFullYear();
|
||||||
|
const month = String(today.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要+1
|
||||||
|
const day = String(today.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
// 常见格式:YYYY-MM-DD
|
||||||
|
const formattedDate = `${year}-${month}-${day}`;
|
||||||
|
const formattedYM = `${year}-${month}`;
|
||||||
|
const list = ref([])
|
||||||
|
const message=useMessage()
|
||||||
|
|
||||||
|
function goBackToday() {
|
||||||
|
setTimeout(() => {
|
||||||
|
nextTick(
|
||||||
|
() => {
|
||||||
|
const elementById = document.getElementById(formattedDate);
|
||||||
|
if (elementById) {
|
||||||
|
elementById.scrollIntoView({
|
||||||
|
behavior: 'auto',
|
||||||
|
block: 'start'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
ClsCalendar().then(res => {
|
||||||
|
list.value = res
|
||||||
|
goBackToday();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function getweekday(date){
|
||||||
|
let day=parse(date, 'yyyy-MM-dd', new Date())
|
||||||
|
return format(day, 'EEEE', {locale: zhCN})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- <n-timeline size="large" style="text-align: left">-->
|
||||||
|
<!-- <n-timeline-item v-for="item in list" :key="item.date" :title="item.date" type="info" >-->
|
||||||
|
<!-- <n-list>-->
|
||||||
|
<!-- <n-list-item v-for="l in item.list" :key="l.article_id ">-->
|
||||||
|
<!-- <n-text>{{l.title}}</n-text>-->
|
||||||
|
<!-- </n-list-item>-->
|
||||||
|
<!-- </n-list>-->
|
||||||
|
<!-- </n-timeline-item>-->
|
||||||
|
<!-- </n-timeline>-->
|
||||||
|
|
||||||
|
<n-list bordered style="max-height: calc(100vh - 230px);text-align: left;">
|
||||||
|
<n-scrollbar style="max-height: calc(100vh - 230px);" >
|
||||||
|
<n-list-item v-for="(item, index) in list" :id="item.calendar_day" :key="item.calendar_day">
|
||||||
|
<n-thing :title="item.calendar_day +' '+item.week">
|
||||||
|
<n-list :bordered="false" hoverable>
|
||||||
|
<n-list-item v-for="(l,i ) in item.items" :key="l.id ">
|
||||||
|
<n-flex justify="space-between">
|
||||||
|
<n-text :type="item.calendar_day===formattedDate?'warning':'info'">{{i+1}}# {{l.title}}
|
||||||
|
<n-tag v-if="l.event" size="small" round type="success">事件</n-tag>
|
||||||
|
<n-tag v-if="l.economic" size="small" round type="error">数据</n-tag>
|
||||||
|
</n-text>
|
||||||
|
<n-rate v-if="l.event&&(l.event.star>0)" readonly :default-value="l.event.star">
|
||||||
|
<n-icon :component="Star48Filled"/>
|
||||||
|
</n-rate>
|
||||||
|
<n-rate v-if="l.economic&&(l.economic.star>0)" readonly :default-value="l.economic.star" >
|
||||||
|
<n-icon :component="Star48Filled"/>
|
||||||
|
</n-rate>
|
||||||
|
</n-flex>
|
||||||
|
|
||||||
|
<n-flex v-if="l.economic">
|
||||||
|
<n-tag type="warning" :bordered="false" :size="'small'">公布:{{l.economic.actual }}</n-tag>
|
||||||
|
<n-tag type="warning" :bordered="false" :size="'small'">预测:{{l.economic.consensus}}</n-tag>
|
||||||
|
<n-tag type="warning" :bordered="false" :size="'small'">前值:{{l.economic.front}}</n-tag>
|
||||||
|
</n-flex>
|
||||||
|
</n-list-item>
|
||||||
|
</n-list>
|
||||||
|
</n-thing>
|
||||||
|
</n-list-item>
|
||||||
|
<n-list-item v-if="list.length==0">
|
||||||
|
<n-text type="info">没有数据</n-text>
|
||||||
|
</n-list-item>
|
||||||
|
<n-list-item v-else style="text-align: center;">
|
||||||
|
<n-button-group>
|
||||||
|
<n-button strong secondary type="warning" @click="goBackToday">回到今天</n-button>
|
||||||
|
</n-button-group>
|
||||||
|
</n-list-item>
|
||||||
|
</n-scrollbar>
|
||||||
|
</n-list>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
108
frontend/src/components/InvestCalendarTimeLine.vue
Normal file
108
frontend/src/components/InvestCalendarTimeLine.vue
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {nextTick, onBeforeMount, onMounted, onUnmounted, ref} from 'vue'
|
||||||
|
import {InvestCalendarTimeLine} from "../../wailsjs/go/main/App";
|
||||||
|
import { addMonths, format ,parse} from 'date-fns';
|
||||||
|
import { zhCN } from 'date-fns/locale';
|
||||||
|
|
||||||
|
import {useMessage} from 'naive-ui'
|
||||||
|
import {Star48Filled} from "@vicons/fluent";
|
||||||
|
const today = new Date();
|
||||||
|
const year = today.getFullYear();
|
||||||
|
const month = String(today.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要+1
|
||||||
|
const day = String(today.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
// 常见格式:YYYY-MM-DD
|
||||||
|
const formattedDate = `${year}-${month}-${day}`;
|
||||||
|
const formattedYM = `${year}-${month}`;
|
||||||
|
const list = ref([])
|
||||||
|
const message=useMessage()
|
||||||
|
|
||||||
|
function goBackToday() {
|
||||||
|
setTimeout(() => {
|
||||||
|
nextTick(
|
||||||
|
() => {
|
||||||
|
const elementById = document.getElementById(formattedDate);
|
||||||
|
if (elementById) {
|
||||||
|
elementById.scrollIntoView({
|
||||||
|
behavior: 'auto',
|
||||||
|
block: 'start'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
InvestCalendarTimeLine(formattedYM).then(res => {
|
||||||
|
list.value = res
|
||||||
|
goBackToday();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
onMounted(()=>{
|
||||||
|
|
||||||
|
})
|
||||||
|
function loadMore(){
|
||||||
|
if (list.value.length>0){
|
||||||
|
let day=parse(list.value[list.value.length-1].date, 'yyyy-MM-dd', new Date())
|
||||||
|
let nextMonth=addMonths(day,1)
|
||||||
|
let ym = format(nextMonth, 'yyyy-MM');
|
||||||
|
console.log(ym)
|
||||||
|
InvestCalendarTimeLine(ym).then(res => {
|
||||||
|
if (res.length==0){
|
||||||
|
message.warning("没有更多数据了")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list.value.push( ...res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getweekday(date){
|
||||||
|
let day=parse(date, 'yyyy-MM-dd', new Date())
|
||||||
|
return format(day, 'EEEE', {locale: zhCN})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- <n-timeline size="large" style="text-align: left">-->
|
||||||
|
<!-- <n-timeline-item v-for="item in list" :key="item.date" :title="item.date" type="info" >-->
|
||||||
|
<!-- <n-list>-->
|
||||||
|
<!-- <n-list-item v-for="l in item.list" :key="l.article_id ">-->
|
||||||
|
<!-- <n-text>{{l.title}}</n-text>-->
|
||||||
|
<!-- </n-list-item>-->
|
||||||
|
<!-- </n-list>-->
|
||||||
|
<!-- </n-timeline-item>-->
|
||||||
|
<!-- </n-timeline>-->
|
||||||
|
|
||||||
|
<n-list bordered style="max-height: calc(100vh - 230px);text-align: left;">
|
||||||
|
<n-scrollbar style="max-height: calc(100vh - 230px);" >
|
||||||
|
<n-list-item v-for="(item, index) in list" :id="item.date" :key="item.date">
|
||||||
|
<n-thing :title="item.date+' '+getweekday(item.date)">
|
||||||
|
<n-list :bordered="false" hoverable>
|
||||||
|
<n-list-item v-for="(l,i ) in item.list" :key="l.article_id ">
|
||||||
|
<n-flex justify="space-between">
|
||||||
|
<n-text :type="item.date===formattedDate?'warning':'info'">{{i+1}}# {{l.title}}</n-text>
|
||||||
|
<n-rate v-if="l.like_count>0" readonly :default-value="l.like_count" :count="l.like_count" >
|
||||||
|
<n-icon :component="Star48Filled"/>
|
||||||
|
</n-rate>
|
||||||
|
</n-flex>
|
||||||
|
</n-list-item>
|
||||||
|
</n-list>
|
||||||
|
</n-thing>
|
||||||
|
</n-list-item>
|
||||||
|
<n-list-item v-if="list.length==0">
|
||||||
|
<n-text type="info">没有数据</n-text>
|
||||||
|
</n-list-item>
|
||||||
|
<n-list-item v-else style="text-align: center;">
|
||||||
|
<n-button-group>
|
||||||
|
<n-button strong secondary type="info" @click="loadMore">加载更多</n-button>
|
||||||
|
<n-button strong secondary type="warning" @click="goBackToday">回到今天</n-button>
|
||||||
|
</n-button-group>
|
||||||
|
</n-list-item>
|
||||||
|
</n-scrollbar>
|
||||||
|
</n-list>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
126
frontend/src/components/SelectStock.vue
Normal file
126
frontend/src/components/SelectStock.vue
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {h, onBeforeMount, onMounted, onUnmounted, ref} from 'vue'
|
||||||
|
import {SearchStock} from "../../wailsjs/go/main/App";
|
||||||
|
import {useMessage, NText, NTag} from 'naive-ui'
|
||||||
|
const message = useMessage()
|
||||||
|
const search = ref('科技股;换手率连续3日大于2')
|
||||||
|
const columns = ref([])
|
||||||
|
const dataList = ref([])
|
||||||
|
|
||||||
|
function Search() {
|
||||||
|
const loading = message.loading("正在获取选股数据...", {duration: 0});
|
||||||
|
SearchStock(search.value).then(res => {
|
||||||
|
loading.destroy()
|
||||||
|
//console.log(res)
|
||||||
|
if(res.code==100){
|
||||||
|
message.success(res.msg)
|
||||||
|
columns.value=res.data.result.columns.filter(item=>!item.hiddenNeed&&(item.title!="市场码"&&item.title!="市场简称")).map(item=>{
|
||||||
|
|
||||||
|
if(item.children){
|
||||||
|
return {
|
||||||
|
title:item.title+(item.unit?'['+item.unit+']':''),
|
||||||
|
key:item.key,
|
||||||
|
resizable: true,
|
||||||
|
minWidth:200,
|
||||||
|
ellipsis: {
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
children:item.children.filter(item=>!item.hiddenNeed).map(item=>{
|
||||||
|
return {
|
||||||
|
title:item.dateMsg,
|
||||||
|
key:item.key,
|
||||||
|
minWidth:100,
|
||||||
|
resizable: true,
|
||||||
|
ellipsis: {
|
||||||
|
tooltip: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return {
|
||||||
|
title:item.title+(item.unit?'['+item.unit+']':''),
|
||||||
|
key:item.key,
|
||||||
|
resizable: true,
|
||||||
|
minWidth:100,
|
||||||
|
ellipsis: {
|
||||||
|
tooltip: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dataList.value=res.data.result.dataList
|
||||||
|
}else {
|
||||||
|
message.error(res.msg)
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
message.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function isNumeric(value) {
|
||||||
|
return !isNaN(parseFloat(value)) && isFinite(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
Search()
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<n-flex>
|
||||||
|
<n-input-group>
|
||||||
|
<n-input v-model:value="search" placeholder="请输入选股指标或者要求" />
|
||||||
|
<n-button type="success" @click="Search">搜索A股</n-button>
|
||||||
|
</n-input-group>
|
||||||
|
</n-flex>
|
||||||
|
<!-- <n-table striped size="small">-->
|
||||||
|
<!-- <n-thead>-->
|
||||||
|
<!-- <n-tr>-->
|
||||||
|
<!-- <n-th v-for="item in columns">{{item.title}}</n-th>-->
|
||||||
|
<!-- </n-tr>-->
|
||||||
|
<!-- </n-thead>-->
|
||||||
|
<!-- <n-tbody>-->
|
||||||
|
<!-- <n-tr v-for="(item,index) in dataList">-->
|
||||||
|
<!-- <n-td v-for="d in columns">{{item[d.key]}}</n-td>-->
|
||||||
|
<!-- </n-tr>-->
|
||||||
|
<!-- </n-tbody>-->
|
||||||
|
<!-- </n-table>-->
|
||||||
|
<n-data-table
|
||||||
|
:max-height="'calc(100vh - 285px)'"
|
||||||
|
size="small"
|
||||||
|
:columns="columns"
|
||||||
|
:data="dataList"
|
||||||
|
:pagination="false"
|
||||||
|
:scroll-x="1800"
|
||||||
|
:render-cell="(value, rowData, column) => {
|
||||||
|
|
||||||
|
if(column.key=='SECURITY_CODE'||column.key=='SERIAL'){
|
||||||
|
return h(NText, { type: 'info',border: false }, { default: () => `${value}` })
|
||||||
|
}
|
||||||
|
if (isNumeric(value)) {
|
||||||
|
let type='info';
|
||||||
|
if (Number(value)<0){
|
||||||
|
type='success';
|
||||||
|
}
|
||||||
|
if(Number(value)>=0&&Number(value)<=5){
|
||||||
|
type='warning';
|
||||||
|
}
|
||||||
|
if (Number(value)>5){
|
||||||
|
type='error';
|
||||||
|
}
|
||||||
|
return h(NText, { type: type }, { default: () => `${value}` })
|
||||||
|
}else{
|
||||||
|
if(column.key=='SECURITY_SHORT_NAME'){
|
||||||
|
return h(NTag, { type: 'info',bordered: false }, { default: () => `${value}` })
|
||||||
|
}else{
|
||||||
|
return h(NText, { type: 'info' }, { default: () => `${value}` })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -29,6 +29,9 @@ import IndustryResearchReportList from "./IndustryResearchReportList.vue";
|
|||||||
import HotStockList from "./HotStockList.vue";
|
import HotStockList from "./HotStockList.vue";
|
||||||
import HotEvents from "./HotEvents.vue";
|
import HotEvents from "./HotEvents.vue";
|
||||||
import HotTopics from "./HotTopics.vue";
|
import HotTopics from "./HotTopics.vue";
|
||||||
|
import InvestCalendarTimeLine from "./InvestCalendarTimeLine.vue";
|
||||||
|
import ClsCalendarTimeLine from "./ClsCalendarTimeLine.vue";
|
||||||
|
import SelectStock from "./SelectStock.vue";
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/master/build/appicon.png');
|
const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/master/build/appicon.png');
|
||||||
@ -584,8 +587,17 @@ function ReFlesh(source) {
|
|||||||
<!-- </n-grid-item>-->
|
<!-- </n-grid-item>-->
|
||||||
</n-grid>
|
</n-grid>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="重大事件时间轴" tab="重大事件时间轴">
|
||||||
|
<InvestCalendarTimeLine />
|
||||||
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="财经日历" tab="财经日历">
|
||||||
|
<ClsCalendarTimeLine />
|
||||||
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="指标选股" tab="指标选股">
|
||||||
|
<select-stock />
|
||||||
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</n-card>
|
</n-card>
|
||||||
<n-modal transform-origin="center" v-model:show="summaryModal" preset="card" style="width: 800px;"
|
<n-modal transform-origin="center" v-model:show="summaryModal" preset="card" style="width: 800px;"
|
||||||
|
6
frontend/wailsjs/go/main/App.d.ts
vendored
6
frontend/wailsjs/go/main/App.d.ts
vendored
@ -15,6 +15,8 @@ export function AnalyzeSentiment(arg1:string):Promise<data.SentimentResult>;
|
|||||||
|
|
||||||
export function CheckUpdate():Promise<void>;
|
export function CheckUpdate():Promise<void>;
|
||||||
|
|
||||||
|
export function ClsCalendar():Promise<Array<any>>;
|
||||||
|
|
||||||
export function DelPrompt(arg1:number):Promise<string>;
|
export function DelPrompt(arg1:number):Promise<string>;
|
||||||
|
|
||||||
export function EMDictCode(arg1:string):Promise<Array<any>>;
|
export function EMDictCode(arg1:string):Promise<Array<any>>;
|
||||||
@ -73,6 +75,8 @@ export function HotTopic(arg1:number):Promise<Array<any>>;
|
|||||||
|
|
||||||
export function IndustryResearchReport(arg1:string):Promise<Array<any>>;
|
export function IndustryResearchReport(arg1:string):Promise<Array<any>>;
|
||||||
|
|
||||||
|
export function InvestCalendarTimeLine(arg1:string):Promise<Array<any>>;
|
||||||
|
|
||||||
export function LongTigerRank(arg1:string):Promise<any>;
|
export function LongTigerRank(arg1:string):Promise<any>;
|
||||||
|
|
||||||
export function NewChatStream(arg1:string,arg2:string,arg3:string,arg4:any):Promise<void>;
|
export function NewChatStream(arg1:string,arg2:string,arg3:string,arg4:any):Promise<void>;
|
||||||
@ -89,6 +93,8 @@ export function SaveAIResponseResult(arg1:string,arg2:string,arg3:string,arg4:st
|
|||||||
|
|
||||||
export function SaveAsMarkdown(arg1:string,arg2:string):Promise<string>;
|
export function SaveAsMarkdown(arg1:string,arg2:string):Promise<string>;
|
||||||
|
|
||||||
|
export function SearchStock(arg1:string):Promise<Record<string, any>>;
|
||||||
|
|
||||||
export function SendDingDingMessage(arg1:string,arg2:string):Promise<string>;
|
export function SendDingDingMessage(arg1:string,arg2:string):Promise<string>;
|
||||||
|
|
||||||
export function SendDingDingMessageByType(arg1:string,arg2:string,arg3:number):Promise<string>;
|
export function SendDingDingMessageByType(arg1:string,arg2:string,arg3:number):Promise<string>;
|
||||||
|
@ -26,6 +26,10 @@ export function CheckUpdate() {
|
|||||||
return window['go']['main']['App']['CheckUpdate']();
|
return window['go']['main']['App']['CheckUpdate']();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ClsCalendar() {
|
||||||
|
return window['go']['main']['App']['ClsCalendar']();
|
||||||
|
}
|
||||||
|
|
||||||
export function DelPrompt(arg1) {
|
export function DelPrompt(arg1) {
|
||||||
return window['go']['main']['App']['DelPrompt'](arg1);
|
return window['go']['main']['App']['DelPrompt'](arg1);
|
||||||
}
|
}
|
||||||
@ -142,6 +146,10 @@ export function IndustryResearchReport(arg1) {
|
|||||||
return window['go']['main']['App']['IndustryResearchReport'](arg1);
|
return window['go']['main']['App']['IndustryResearchReport'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function InvestCalendarTimeLine(arg1) {
|
||||||
|
return window['go']['main']['App']['InvestCalendarTimeLine'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function LongTigerRank(arg1) {
|
export function LongTigerRank(arg1) {
|
||||||
return window['go']['main']['App']['LongTigerRank'](arg1);
|
return window['go']['main']['App']['LongTigerRank'](arg1);
|
||||||
}
|
}
|
||||||
@ -174,6 +182,10 @@ export function SaveAsMarkdown(arg1, arg2) {
|
|||||||
return window['go']['main']['App']['SaveAsMarkdown'](arg1, arg2);
|
return window['go']['main']['App']['SaveAsMarkdown'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SearchStock(arg1) {
|
||||||
|
return window['go']['main']['App']['SearchStock'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function SendDingDingMessage(arg1, arg2) {
|
export function SendDingDingMessage(arg1, arg2) {
|
||||||
return window['go']['main']['App']['SendDingDingMessage'](arg1, arg2);
|
return window['go']['main']['App']['SendDingDingMessage'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user