mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
Compare commits
No commits in common. "master" and "v2025.5.14.1-alpha" have entirely different histories.
master
...
v2025.5.14
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
# Match any new tag
|
# Match any new tag
|
||||||
- '*-release'
|
- '*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Necessary for most environments as build failure can occur due to OOM issues
|
# Necessary for most environments as build failure can occur due to OOM issues
|
||||||
@ -47,4 +47,4 @@ jobs:
|
|||||||
go-version: '1.24'
|
go-version: '1.24'
|
||||||
build-tags: ${{ github.ref_name }}
|
build-tags: ${{ github.ref_name }}
|
||||||
build-commit-message: ${{ steps.get_commit_message.outputs.commit_message }}
|
build-commit-message: ${{ steps.get_commit_message.outputs.commit_message }}
|
||||||
node-version: '20.x'
|
node-version: '18.x'
|
||||||
|
26
README.md
26
README.md
@ -3,15 +3,14 @@
|
|||||||

|

|
||||||
[](https://github.com/ArvinLovegood/go-stock)
|
[](https://github.com/ArvinLovegood/go-stock)
|
||||||
[](https://gitee.com/arvinlovegood_admin/go-stock)
|
[](https://gitee.com/arvinlovegood_admin/go-stock)
|
||||||
|
[](https://gitcode.com/ArvinLovegood/go-stock)
|
||||||
[//]: # ([](https://gitcode.com/ArvinLovegood/go-stock))
|
|
||||||
|
|
||||||
### 🌟公众号
|
### 🌟公众号
|
||||||

|

|
||||||
|
|
||||||
### 📈 交流群
|
### 📈 交流群
|
||||||
- QQ交流群2:[点击链接加入群聊【go-stock交流群2】:892666282](https://qm.qq.com/q/5mYiy6Yxh0)
|
- QQ交流群2:[点击链接加入群聊【go-stock交流群2】:892666282](https://qm.qq.com/q/5mYiy6Yxh0)
|
||||||
- QQ交流群:[点击链接加入群聊【go-stock交流群】:491605333(已满会定期清理,随缘入群)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0YQ8qD3exahsD4YLNhzQTWe5ssstWC89&authKey=usOMMRFtIQDC%2FYcatHYapcxQbJ7PwXPHK9OypTXWzNjAq%2FRVvQu9bj2lRgb%2BSZ3p&noverify=0&group_code=491605333)
|
- QQ交流群:[点击链接加入群聊【go-stock交流群】:491605333(已满)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0YQ8qD3exahsD4YLNhzQTWe5ssstWC89&authKey=usOMMRFtIQDC%2FYcatHYapcxQbJ7PwXPHK9OypTXWzNjAq%2FRVvQu9bj2lRgb%2BSZ3p&noverify=0&group_code=491605333)
|
||||||
|
|
||||||
### ✨ 简介
|
### ✨ 简介
|
||||||
- 本项目基于Wails和NaiveUI开发,结合AI大模型构建的股票分析工具。
|
- 本项目基于Wails和NaiveUI开发,结合AI大模型构建的股票分析工具。
|
||||||
@ -27,16 +26,15 @@
|
|||||||
|
|
||||||
### 💬 支持大模型/平台
|
### 💬 支持大模型/平台
|
||||||
| 模型 | 状态 | 备注 |
|
| 模型 | 状态 | 备注 |
|
||||||
| --- | --- |---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| --- | --- |-----------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| [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://www.compshare.cn/image-community?ytag=GPU_YY-gh_gostock) |
|
| [大模型聚合平台](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) |
|
||||||
|
|
||||||
### <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)
|
||||||
@ -47,8 +45,6 @@
|
|||||||
## 🧩 重大功能开发计划
|
## 🧩 重大功能开发计划
|
||||||
| 功能说明 | 状态 | 备注 |
|
| 功能说明 | 状态 | 备注 |
|
||||||
|-----------------|----|----------------------------------------------------------------------------------------------------------|
|
|-----------------|----|----------------------------------------------------------------------------------------------------------|
|
||||||
| 股票分析知识库 | 🚧 | 未来计划 |
|
|
||||||
| Ai智能选股 | 🚧 | Ai智能选股功能开发中(下半年重点开发计划) |
|
|
||||||
| ETF支持 | 🚧 | ETF数据支持 (目前可以查看净值和估值) |
|
| ETF支持 | 🚧 | ETF数据支持 (目前可以查看净值和估值) |
|
||||||
| 美股支持 | ✅ | 美股数据支持 |
|
| 美股支持 | ✅ | 美股数据支持 |
|
||||||
| 港股支持 | ✅ | 港股数据支持 |
|
| 港股支持 | ✅ | 港股数据支持 |
|
||||||
@ -57,20 +53,6 @@
|
|||||||
| 不再强制依赖Chrome浏览器 | ✅ | 默认使用edge浏览器抓取新闻资讯 |
|
| 不再强制依赖Chrome浏览器 | ✅ | 默认使用edge浏览器抓取新闻资讯 |
|
||||||
|
|
||||||
## 👀 更新日志
|
## 👀 更新日志
|
||||||
### 2025.06.30 添加指标选股功能
|
|
||||||
### 2025.06.27 添加财经日历和重大事件时间轴功能
|
|
||||||
### 2025.06.25 添加热门股票、事件和话题功能
|
|
||||||
### 2025.06.18 更新内置股票基础数据,软件内实时市场资讯信息提醒,添加行业研究功能
|
|
||||||
### 2025.06.15 添加公司公告信息搜索/查看功能
|
|
||||||
### 2025.06.15 添加个股研报到弹出菜单
|
|
||||||
### 2025.06.13 添加个股研报功能
|
|
||||||
### 2025.06.12 添加龙虎榜功能,新增行业排名分类
|
|
||||||
### 2025.05.30 优化股票分时图显示
|
|
||||||
### 2025.05.20 修复财联社电报获取问题
|
|
||||||
### 2025.05.16 优化资金趋势图表组件
|
|
||||||
### 2025.05.15 重构应用加载和数据初始化逻辑,添加股票资金趋势功能,资金趋势图表增加主力当日净流入数据并优化展示效果
|
|
||||||
### 2025.05.14 添加个股资金流向功能,排行榜增加股票行情K线图弹窗
|
|
||||||
### 2025.05.13 添加行业排名功能
|
|
||||||
### 2025.05.09 添加A股盘口数据解析和展示功能
|
### 2025.05.09 添加A股盘口数据解析和展示功能
|
||||||
### 2025.05.07 优化分时图的展示
|
### 2025.05.07 优化分时图的展示
|
||||||
### 2025.04.29 补全港股/美股基础数据,优化港股股价延迟问题,优化初始化逻辑
|
### 2025.04.29 补全港股/美股基础数据,优化港股股价延迟问题,优化初始化逻辑
|
||||||
|
41
app.go
41
app.go
@ -139,22 +139,6 @@ func (a *App) CheckUpdate() {
|
|||||||
func (a *App) domReady(ctx context.Context) {
|
func (a *App) domReady(ctx context.Context) {
|
||||||
defer PanicHandler()
|
defer PanicHandler()
|
||||||
|
|
||||||
if stocksBin != nil && len(stocksBin) > 0 {
|
|
||||||
go runtime.EventsEmit(a.ctx, "loadingMsg", "检查A股基础信息...")
|
|
||||||
go initStockData(a.ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stocksBinHK != nil && len(stocksBinHK) > 0 {
|
|
||||||
go runtime.EventsEmit(a.ctx, "loadingMsg", "检查港股基础信息...")
|
|
||||||
go initStockDataHK(a.ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stocksBinUS != nil && len(stocksBinUS) > 0 {
|
|
||||||
go runtime.EventsEmit(a.ctx, "loadingMsg", "检查美股基础信息...")
|
|
||||||
go initStockDataUS(a.ctx)
|
|
||||||
}
|
|
||||||
updateBasicInfo()
|
|
||||||
|
|
||||||
// Add your action here
|
// Add your action here
|
||||||
//定时更新数据
|
//定时更新数据
|
||||||
config := data.NewSettingsApi(&data.Settings{}).GetConfig()
|
config := data.NewSettingsApi(&data.Settings{}).GetConfig()
|
||||||
@ -178,9 +162,6 @@ func (a *App) domReady(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
entryID, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval+10), func() {
|
entryID, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval+10), func() {
|
||||||
news := data.NewMarketNewsApi().GetNewTelegraph(30)
|
news := data.NewMarketNewsApi().GetNewTelegraph(30)
|
||||||
if config.EnablePushNews {
|
|
||||||
go a.NewsPush(news)
|
|
||||||
}
|
|
||||||
go runtime.EventsEmit(a.ctx, "newTelegraph", news)
|
go runtime.EventsEmit(a.ctx, "newTelegraph", news)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -191,9 +172,6 @@ func (a *App) domReady(ctx context.Context) {
|
|||||||
|
|
||||||
entryIDSina, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval+10), func() {
|
entryIDSina, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval+10), func() {
|
||||||
news := data.NewMarketNewsApi().GetSinaNews(30)
|
news := data.NewMarketNewsApi().GetSinaNews(30)
|
||||||
if config.EnablePushNews {
|
|
||||||
go a.NewsPush(news)
|
|
||||||
}
|
|
||||||
go runtime.EventsEmit(a.ctx, "newSinaNews", news)
|
go runtime.EventsEmit(a.ctx, "newSinaNews", news)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -298,15 +276,6 @@ func (a *App) domReady(ctx context.Context) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) NewsPush(news *[]models.Telegraph) {
|
|
||||||
for _, telegraph := range *news {
|
|
||||||
//if telegraph.IsRed {
|
|
||||||
go runtime.EventsEmit(a.ctx, "newsPush", telegraph)
|
|
||||||
go data.NewAlertWindowsApi("go-stock", telegraph.Source+" "+telegraph.Time, telegraph.Content, string(icon)).SendNotification()
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) AddCronTask(follow data.FollowedStock) func() {
|
func (a *App) AddCronTask(follow data.FollowedStock) func() {
|
||||||
return func() {
|
return func() {
|
||||||
go runtime.EventsEmit(a.ctx, "warnMsg", "开始自动分析"+follow.Name+"_"+follow.StockCode)
|
go runtime.EventsEmit(a.ctx, "warnMsg", "开始自动分析"+follow.Name+"_"+follow.StockCode)
|
||||||
@ -1138,17 +1107,11 @@ func (a *App) GetIndustryRank(sort string, cnt int) []any {
|
|||||||
res := data.NewMarketNewsApi().GetIndustryRank(sort, cnt)
|
res := data.NewMarketNewsApi().GetIndustryRank(sort, cnt)
|
||||||
return res["data"].([]any)
|
return res["data"].([]any)
|
||||||
}
|
}
|
||||||
func (a *App) GetIndustryMoneyRankSina(fenlei, sort string) []map[string]any {
|
func (a *App) GetIndustryMoneyRankSina(fenlei string) []map[string]any {
|
||||||
res := data.NewMarketNewsApi().GetIndustryMoneyRankSina(fenlei, sort)
|
res := data.NewMarketNewsApi().GetIndustryMoneyRankSina(fenlei)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
func (a *App) GetMoneyRankSina(sort string) []map[string]any {
|
func (a *App) GetMoneyRankSina(sort string) []map[string]any {
|
||||||
res := data.NewMarketNewsApi().GetMoneyRankSina(sort)
|
res := data.NewMarketNewsApi().GetMoneyRankSina(sort)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetStockMoneyTrendByDay(stockCode string, days int) []map[string]any {
|
|
||||||
res := data.NewMarketNewsApi().GetStockMoneyTrendByDay(stockCode, days)
|
|
||||||
slice.Reverse(res)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-stock/backend/data"
|
|
||||||
"go-stock/backend/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @Author spark
|
|
||||||
// @Date 2025/6/8 20:45
|
|
||||||
// @Desc
|
|
||||||
//-----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func (a *App) LongTigerRank(date string) *[]models.LongTigerRankData {
|
|
||||||
return data.NewMarketNewsApi().LongTiger(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) StockResearchReport(stockCode string) []any {
|
|
||||||
return data.NewMarketNewsApi().StockResearchReport(stockCode, 7)
|
|
||||||
}
|
|
||||||
func (a *App) StockNotice(stockCode string) []any {
|
|
||||||
return data.NewMarketNewsApi().StockNotice(stockCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) IndustryResearchReport(industryCode string) []any {
|
|
||||||
return data.NewMarketNewsApi().IndustryResearchReport(industryCode, 7)
|
|
||||||
}
|
|
||||||
func (a App) EMDictCode(code string) []any {
|
|
||||||
return data.NewMarketNewsApi().EMDictCode(code, a.cache)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a App) AnalyzeSentiment(text string) data.SentimentResult {
|
|
||||||
return data.AnalyzeSentiment(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a App) HotStock(marketType string) *[]models.HotItem {
|
|
||||||
return data.NewMarketNewsApi().XUEQIUHotStock(100, marketType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a App) HotEvent(size int) *[]models.HotEvent {
|
|
||||||
if size <= 0 {
|
|
||||||
size = 10
|
|
||||||
}
|
|
||||||
return data.NewMarketNewsApi().HotEvent(size)
|
|
||||||
}
|
|
||||||
func (a App) HotTopic(size int) []any {
|
|
||||||
if size <= 0 {
|
|
||||||
size = 10
|
|
||||||
}
|
|
||||||
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()
|
|
||||||
}
|
|
@ -1,17 +1,13 @@
|
|||||||
package data
|
package data
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/coocood/freecache"
|
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
|
||||||
"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"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"go-stock/backend/db"
|
"go-stock/backend/db"
|
||||||
"go-stock/backend/logger"
|
"go-stock/backend/logger"
|
||||||
"go-stock/backend/models"
|
"go-stock/backend/models"
|
||||||
@ -41,7 +37,7 @@ func (m MarketNewsApi) GetNewTelegraph(crawlTimeOut int64) *[]models.Telegraph {
|
|||||||
//logger.SugaredLogger.Info(string(response.Body()))
|
//logger.SugaredLogger.Info(string(response.Body()))
|
||||||
document, _ := goquery.NewDocumentFromReader(strings.NewReader(string(response.Body())))
|
document, _ := goquery.NewDocumentFromReader(strings.NewReader(string(response.Body())))
|
||||||
|
|
||||||
document.Find(".telegraph-content-box").Each(func(i int, selection *goquery.Selection) {
|
document.Find(".telegraph-list").Each(func(i int, selection *goquery.Selection) {
|
||||||
//logger.SugaredLogger.Info(selection.Text())
|
//logger.SugaredLogger.Info(selection.Text())
|
||||||
telegraph := models.Telegraph{Source: "财联社电报"}
|
telegraph := models.Telegraph{Source: "财联社电报"}
|
||||||
spans := selection.Find("div.telegraph-content-box span")
|
spans := selection.Find("div.telegraph-content-box span")
|
||||||
@ -73,7 +69,6 @@ func (m MarketNewsApi) GetNewTelegraph(crawlTimeOut int64) *[]models.Telegraph {
|
|||||||
|
|
||||||
//telegraph = append(telegraph, ReplaceSensitiveWords(selection.Text()))
|
//telegraph = append(telegraph, ReplaceSensitiveWords(selection.Text()))
|
||||||
if telegraph.Content != "" {
|
if telegraph.Content != "" {
|
||||||
telegraph.SentimentResult = AnalyzeSentiment(telegraph.Content).Description
|
|
||||||
cnt := int64(0)
|
cnt := int64(0)
|
||||||
db.Dao.Model(telegraph).Where("time=? and source=?", telegraph.Time, telegraph.Source).Count(&cnt)
|
db.Dao.Model(telegraph).Where("time=? and source=?", telegraph.Time, telegraph.Source).Count(&cnt)
|
||||||
if cnt == 0 {
|
if cnt == 0 {
|
||||||
@ -143,7 +138,8 @@ func (m MarketNewsApi) GetSinaNews(crawlTimeOut uint) *[]models.Telegraph {
|
|||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60").
|
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60").
|
||||||
Get("https://zhibo.sina.com.cn/api/zhibo/feed?callback=callback&page=1&page_size=20&zhibo_id=152&tag_id=0&dire=f&dpc=1&pagesize=20&id=4161089&type=0&_=" + strconv.FormatInt(time.Now().Unix(), 10))
|
Get("https://zhibo.sina.com.cn/api/zhibo/feed?callback=callback&page=1&page_size=20&zhibo_id=152&tag_id=0&dire=f&dpc=1&pagesize=20&id=4161089&type=0&_=" + strconv.FormatInt(time.Now().Unix(), 10))
|
||||||
js := string(response.Body())
|
js := string(response.Body())
|
||||||
js = strutil.ReplaceWithMap(js, map[string]string{
|
js = strutil.ReplaceWithMap(js,
|
||||||
|
map[string]string{
|
||||||
"try{callback(": "var data=",
|
"try{callback(": "var data=",
|
||||||
");}catch(e){};": ";",
|
");}catch(e){};": ";",
|
||||||
})
|
})
|
||||||
@ -193,7 +189,6 @@ func (m MarketNewsApi) GetSinaNews(crawlTimeOut uint) *[]models.Telegraph {
|
|||||||
logger.SugaredLogger.Infof("telegraph.SubjectTags:%v %s", telegraph.SubjectTags, telegraph.Content)
|
logger.SugaredLogger.Infof("telegraph.SubjectTags:%v %s", telegraph.SubjectTags, telegraph.Content)
|
||||||
|
|
||||||
if telegraph.Content != "" {
|
if telegraph.Content != "" {
|
||||||
telegraph.SentimentResult = AnalyzeSentiment(telegraph.Content).Description
|
|
||||||
cnt := int64(0)
|
cnt := int64(0)
|
||||||
db.Dao.Model(telegraph).Where("time=? and source=?", telegraph.Time, telegraph.Source).Count(&cnt)
|
db.Dao.Model(telegraph).Where("time=? and source=?", telegraph.Time, telegraph.Source).Count(&cnt)
|
||||||
if cnt == 0 {
|
if cnt == 0 {
|
||||||
@ -243,8 +238,8 @@ func (m MarketNewsApi) GetIndustryRank(sort string, cnt int) map[string]any {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m MarketNewsApi) GetIndustryMoneyRankSina(fenlei, sort string) []map[string]any {
|
func (m MarketNewsApi) GetIndustryMoneyRankSina(fenlei string) []map[string]any {
|
||||||
url := fmt.Sprintf("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/MoneyFlow.ssl_bkzj_bk?page=1&num=20&sort=%s&asc=0&fenlei=%s", sort, fenlei)
|
url := fmt.Sprintf("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/MoneyFlow.ssl_bkzj_bk?page=1&num=20&sort=netamount&asc=0&fenlei=%s", fenlei)
|
||||||
|
|
||||||
response, _ := resty.New().SetTimeout(time.Duration(5)*time.Second).R().
|
response, _ := resty.New().SetTimeout(time.Duration(5)*time.Second).R().
|
||||||
SetHeader("Host", "vip.stock.finance.sina.com.cn").
|
SetHeader("Host", "vip.stock.finance.sina.com.cn").
|
||||||
@ -280,424 +275,3 @@ func (m MarketNewsApi) GetMoneyRankSina(sort string) []map[string]any {
|
|||||||
}
|
}
|
||||||
return *res
|
return *res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m MarketNewsApi) GetStockMoneyTrendByDay(stockCode string, days int) []map[string]any {
|
|
||||||
url := fmt.Sprintf("http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/MoneyFlow.ssl_qsfx_zjlrqs?page=1&num=%d&sort=opendate&asc=0&daima=%s", days, stockCode)
|
|
||||||
|
|
||||||
response, _ := resty.New().SetTimeout(time.Duration(5)*time.Second).R().
|
|
||||||
SetHeader("Host", "vip.stock.finance.sina.com.cn").
|
|
||||||
SetHeader("Referer", "https://finance.sina.com.cn").
|
|
||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60").Get(url)
|
|
||||||
js := string(response.Body())
|
|
||||||
res := &[]map[string]any{}
|
|
||||||
err := json.Unmarshal([]byte(js), &res)
|
|
||||||
if err != nil {
|
|
||||||
logger.SugaredLogger.Error(err)
|
|
||||||
return *res
|
|
||||||
}
|
|
||||||
return *res
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) TopStocksRankingList(date string) {
|
|
||||||
url := fmt.Sprintf("http://vip.stock.finance.sina.com.cn/q/go.php/vInvestConsult/kind/lhb/index.phtml?tradedate=%s", date)
|
|
||||||
response, _ := resty.New().SetTimeout(time.Duration(5)*time.Second).R().
|
|
||||||
SetHeader("Host", "vip.stock.finance.sina.com.cn").
|
|
||||||
SetHeader("Referer", "https://finance.sina.com.cn").
|
|
||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60").Get(url)
|
|
||||||
|
|
||||||
html, _ := convertor.GbkToUtf8(response.Body())
|
|
||||||
//logger.SugaredLogger.Infof("html:%s", html)
|
|
||||||
document, err := goquery.NewDocumentFromReader(bytes.NewReader(html))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
document.Find("table.list_table").Each(func(i int, s *goquery.Selection) {
|
|
||||||
title := strutil.Trim(s.Find("tr:first-child").First().Text())
|
|
||||||
logger.SugaredLogger.Infof("title:%s", title)
|
|
||||||
s.Find("tr:not(:first-child)").Each(func(i int, s *goquery.Selection) {
|
|
||||||
logger.SugaredLogger.Infof("s:%s", strutil.RemoveNonPrintable(s.Text()))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) LongTiger(date string) *[]models.LongTigerRankData {
|
|
||||||
ranks := &[]models.LongTigerRankData{}
|
|
||||||
url := "https://datacenter-web.eastmoney.com/api/data/v1/get"
|
|
||||||
logger.SugaredLogger.Infof("url:%s", url)
|
|
||||||
params := make(map[string]string)
|
|
||||||
params["callback"] = "callback"
|
|
||||||
params["sortColumns"] = "TURNOVERRATE,TRADE_DATE,SECURITY_CODE"
|
|
||||||
params["sortTypes"] = "-1,-1,1"
|
|
||||||
params["pageSize"] = "500"
|
|
||||||
params["pageNumber"] = "1"
|
|
||||||
params["reportName"] = "RPT_DAILYBILLBOARD_DETAILSNEW"
|
|
||||||
params["columns"] = "SECURITY_CODE,SECUCODE,SECURITY_NAME_ABBR,TRADE_DATE,EXPLAIN,CLOSE_PRICE,CHANGE_RATE,BILLBOARD_NET_AMT,BILLBOARD_BUY_AMT,BILLBOARD_SELL_AMT,BILLBOARD_DEAL_AMT,ACCUM_AMOUNT,DEAL_NET_RATIO,DEAL_AMOUNT_RATIO,TURNOVERRATE,FREE_MARKET_CAP,EXPLANATION,D1_CLOSE_ADJCHRATE,D2_CLOSE_ADJCHRATE,D5_CLOSE_ADJCHRATE,D10_CLOSE_ADJCHRATE,SECURITY_TYPE_CODE"
|
|
||||||
params["source"] = "WEB"
|
|
||||||
params["client"] = "WEB"
|
|
||||||
params["filter"] = fmt.Sprintf("(TRADE_DATE<='%s')(TRADE_DATE>='%s')", date, date)
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(15)*time.Second).R().
|
|
||||||
SetHeader("Host", "datacenter-web.eastmoney.com").
|
|
||||||
SetHeader("Referer", "https://data.eastmoney.com/stock/tradedetail.html").
|
|
||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
|
||||||
SetQueryParams(params).
|
|
||||||
Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return ranks
|
|
||||||
}
|
|
||||||
js := string(resp.Body())
|
|
||||||
logger.SugaredLogger.Infof("resp:%s", js)
|
|
||||||
|
|
||||||
js = strutil.ReplaceWithMap(js, map[string]string{
|
|
||||||
"callback(": "var data=",
|
|
||||||
");": ";",
|
|
||||||
})
|
|
||||||
//logger.SugaredLogger.Info(js)
|
|
||||||
vm := otto.New()
|
|
||||||
_, err = vm.Run(js)
|
|
||||||
_, err = vm.Run("var data = JSON.stringify(data);")
|
|
||||||
value, err := vm.Get("data")
|
|
||||||
logger.SugaredLogger.Infof("resp-json:%s", value.String())
|
|
||||||
data := gjson.Get(value.String(), "result.data")
|
|
||||||
logger.SugaredLogger.Infof("resp:%v", data)
|
|
||||||
err = json.Unmarshal([]byte(data.String()), ranks)
|
|
||||||
if err != nil {
|
|
||||||
logger.SugaredLogger.Error(err)
|
|
||||||
return ranks
|
|
||||||
}
|
|
||||||
for _, rankData := range *ranks {
|
|
||||||
temp := &models.LongTigerRankData{}
|
|
||||||
db.Dao.Model(temp).Where(&models.LongTigerRankData{
|
|
||||||
TRADEDATE: rankData.TRADEDATE,
|
|
||||||
SECUCODE: rankData.SECUCODE,
|
|
||||||
}).First(temp)
|
|
||||||
if temp.SECURITYTYPECODE == "" {
|
|
||||||
db.Dao.Model(temp).Create(&rankData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ranks
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) IndustryResearchReport(industryCode string, days int) []any {
|
|
||||||
beginDate := time.Now().Add(-time.Duration(days) * 24 * time.Hour).Format("2006-01-02")
|
|
||||||
endDate := time.Now().Format("2006-01-02")
|
|
||||||
if strutil.Trim(industryCode) != "" {
|
|
||||||
beginDate = time.Now().Add(-time.Duration(days) * 365 * time.Hour).Format("2006-01-02")
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.SugaredLogger.Infof("IndustryResearchReport-name:%s", industryCode)
|
|
||||||
params := map[string]string{
|
|
||||||
"industry": "*",
|
|
||||||
"industryCode": industryCode,
|
|
||||||
"beginTime": beginDate,
|
|
||||||
"endTime": endDate,
|
|
||||||
"pageNo": "1",
|
|
||||||
"pageSize": "50",
|
|
||||||
"p": "1",
|
|
||||||
"pageNum": "1",
|
|
||||||
"pageNumber": "1",
|
|
||||||
"qType": "1",
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "https://reportapi.eastmoney.com/report/list"
|
|
||||||
|
|
||||||
logger.SugaredLogger.Infof("beginDate:%s endDate:%s", beginDate, endDate)
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(15)*time.Second).R().
|
|
||||||
SetHeader("Host", "reportapi.eastmoney.com").
|
|
||||||
SetHeader("Origin", "https://data.eastmoney.com").
|
|
||||||
SetHeader("Referer", "https://data.eastmoney.com/report/stock.jshtml").
|
|
||||||
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").
|
|
||||||
SetQueryParams(params).Get(url)
|
|
||||||
respMap := map[string]any{}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return []any{}
|
|
||||||
}
|
|
||||||
json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
//logger.SugaredLogger.Infof("resp:%+v", respMap["data"])
|
|
||||||
return respMap["data"].([]any)
|
|
||||||
}
|
|
||||||
func (m MarketNewsApi) StockResearchReport(stockCode string, days int) []any {
|
|
||||||
beginDate := time.Now().Add(-time.Duration(days) * 24 * time.Hour).Format("2006-01-02")
|
|
||||||
endDate := time.Now().Format("2006-01-02")
|
|
||||||
if strutil.ContainsAny(stockCode, []string{"."}) {
|
|
||||||
stockCode = strings.Split(stockCode, ".")[0]
|
|
||||||
beginDate = time.Now().Add(-time.Duration(days) * 365 * time.Hour).Format("2006-01-02")
|
|
||||||
} else {
|
|
||||||
stockCode = strutil.ReplaceWithMap(stockCode, map[string]string{
|
|
||||||
"sh": "",
|
|
||||||
"sz": "",
|
|
||||||
"gb_": "",
|
|
||||||
"us": "",
|
|
||||||
"us_": "",
|
|
||||||
})
|
|
||||||
beginDate = time.Now().Add(-time.Duration(days) * 365 * time.Hour).Format("2006-01-02")
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.SugaredLogger.Infof("StockResearchReport-stockCode:%s", stockCode)
|
|
||||||
|
|
||||||
type Req struct {
|
|
||||||
BeginTime string `json:"beginTime"`
|
|
||||||
EndTime string `json:"endTime"`
|
|
||||||
IndustryCode string `json:"industryCode"`
|
|
||||||
RatingChange string `json:"ratingChange"`
|
|
||||||
Rating string `json:"rating"`
|
|
||||||
OrgCode interface{} `json:"orgCode"`
|
|
||||||
Code string `json:"code"`
|
|
||||||
Rcode string `json:"rcode"`
|
|
||||||
PageSize int `json:"pageSize"`
|
|
||||||
PageNo int `json:"pageNo"`
|
|
||||||
P int `json:"p"`
|
|
||||||
PageNum int `json:"pageNum"`
|
|
||||||
PageNumber int `json:"pageNumber"`
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "https://reportapi.eastmoney.com/report/list2"
|
|
||||||
|
|
||||||
logger.SugaredLogger.Infof("beginDate:%s endDate:%s", beginDate, endDate)
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(15)*time.Second).R().
|
|
||||||
SetHeader("Host", "reportapi.eastmoney.com").
|
|
||||||
SetHeader("Origin", "https://data.eastmoney.com").
|
|
||||||
SetHeader("Referer", "https://data.eastmoney.com/report/stock.jshtml").
|
|
||||||
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(&Req{
|
|
||||||
Code: stockCode,
|
|
||||||
IndustryCode: "*",
|
|
||||||
BeginTime: beginDate,
|
|
||||||
EndTime: endDate,
|
|
||||||
PageNo: 1,
|
|
||||||
PageSize: 50,
|
|
||||||
P: 1,
|
|
||||||
PageNum: 1,
|
|
||||||
PageNumber: 1,
|
|
||||||
}).Post(url)
|
|
||||||
respMap := map[string]any{}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return []any{}
|
|
||||||
}
|
|
||||||
json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
//logger.SugaredLogger.Infof("resp:%+v", respMap["data"])
|
|
||||||
return respMap["data"].([]any)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) StockNotice(stock_list string) []any {
|
|
||||||
var stockCodes []string
|
|
||||||
for _, stockCode := range strings.Split(stock_list, ",") {
|
|
||||||
if strutil.ContainsAny(stockCode, []string{"."}) {
|
|
||||||
stockCode = strings.Split(stockCode, ".")[0]
|
|
||||||
stockCodes = append(stockCodes, stockCode)
|
|
||||||
} else {
|
|
||||||
stockCode = strutil.ReplaceWithMap(stockCode, map[string]string{
|
|
||||||
"sh": "",
|
|
||||||
"sz": "",
|
|
||||||
"gb_": "",
|
|
||||||
"us": "",
|
|
||||||
"us_": "",
|
|
||||||
})
|
|
||||||
stockCodes = append(stockCodes, stockCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "https://np-anotice-stock.eastmoney.com/api/security/ann?page_size=50&page_index=1&ann_type=SHA%2CCYB%2CSZA%2CBJA%2CINV&client_source=web&f_node=0&stock_list=" + strings.Join(stockCodes, ",")
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(15)*time.Second).R().
|
|
||||||
SetHeader("Host", "np-anotice-stock.eastmoney.com").
|
|
||||||
SetHeader("Referer", "https://data.eastmoney.com/notices/hsa/5.html").
|
|
||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
|
||||||
Get(url)
|
|
||||||
respMap := map[string]any{}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return []any{}
|
|
||||||
}
|
|
||||||
json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
//logger.SugaredLogger.Infof("resp:%+v", respMap["data"])
|
|
||||||
return (respMap["data"].(map[string]any))["list"].([]any)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) EMDictCode(code string, cache *freecache.Cache) []any {
|
|
||||||
respMap := map[string]any{}
|
|
||||||
|
|
||||||
d, _ := cache.Get([]byte(code))
|
|
||||||
if d != nil {
|
|
||||||
json.Unmarshal(d, &respMap)
|
|
||||||
return respMap["data"].([]any)
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "https://reportapi.eastmoney.com/report/bk"
|
|
||||||
|
|
||||||
params := map[string]string{
|
|
||||||
"bkCode": code,
|
|
||||||
}
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(15)*time.Second).R().
|
|
||||||
SetHeader("Host", "reportapi.eastmoney.com").
|
|
||||||
SetHeader("Origin", "https://data.eastmoney.com").
|
|
||||||
SetHeader("Referer", "https://data.eastmoney.com/report/industry.jshtml").
|
|
||||||
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").
|
|
||||||
SetQueryParams(params).Get(url)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return []any{}
|
|
||||||
}
|
|
||||||
json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
//logger.SugaredLogger.Infof("resp:%+v", respMap["data"])
|
|
||||||
cache.Set([]byte(code), resp.Body(), 60*60*24)
|
|
||||||
return respMap["data"].([]any)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) TradingViewNews() *[]models.TVNews {
|
|
||||||
TVNews := &[]models.TVNews{}
|
|
||||||
url := "https://news-mediator.tradingview.com/news-flow/v2/news?filter=lang:zh-Hans&filter=provider:panews,reuters&client=screener&streaming=false"
|
|
||||||
resp, err := resty.New().SetProxy("http://127.0.0.1:10809").SetTimeout(time.Duration(30)*time.Second).R().
|
|
||||||
SetHeader("Host", "news-mediator.tradingview.com").
|
|
||||||
SetHeader("Origin", "https://cn.tradingview.com").
|
|
||||||
SetHeader("Referer", "https://cn.tradingview.com/").
|
|
||||||
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("TradingViewNews err:%s", err.Error())
|
|
||||||
return TVNews
|
|
||||||
}
|
|
||||||
respMap := map[string]any{}
|
|
||||||
err = json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
if err != nil {
|
|
||||||
return TVNews
|
|
||||||
}
|
|
||||||
items, err := json.Marshal(respMap["items"])
|
|
||||||
if err != nil {
|
|
||||||
return TVNews
|
|
||||||
}
|
|
||||||
json.Unmarshal(items, TVNews)
|
|
||||||
return TVNews
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
res := &models.XUEQIUHot{}
|
|
||||||
_, err = request.
|
|
||||||
SetHeader("Host", "stock.xueqiu.com").
|
|
||||||
SetHeader("Origin", "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("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).
|
|
||||||
Get(url)
|
|
||||||
if err != nil {
|
|
||||||
logger.SugaredLogger.Errorf("XUEQIUHotStock err:%s", err.Error())
|
|
||||||
return &[]models.HotItem{}
|
|
||||||
}
|
|
||||||
logger.SugaredLogger.Infof("XUEQIUHotStock:%+v", res)
|
|
||||||
return &res.Data.Items
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) HotEvent(size int) *[]models.HotEvent {
|
|
||||||
events := &[]models.HotEvent{}
|
|
||||||
url := fmt.Sprintf("https://xueqiu.com/hot_event/list.json?count=%d", size)
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
|
||||||
SetHeader("Host", "xueqiu.com").
|
|
||||||
SetHeader("Origin", "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("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").
|
|
||||||
Get(url)
|
|
||||||
if err != nil {
|
|
||||||
logger.SugaredLogger.Errorf("HotEvent err:%s", err.Error())
|
|
||||||
return events
|
|
||||||
}
|
|
||||||
//logger.SugaredLogger.Infof("HotEvent:%s", resp.Body())
|
|
||||||
respMap := map[string]any{}
|
|
||||||
err = json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
items, err := json.Marshal(respMap["list"])
|
|
||||||
if err != nil {
|
|
||||||
return events
|
|
||||||
}
|
|
||||||
json.Unmarshal(items, events)
|
|
||||||
return events
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MarketNewsApi) HotTopic(size int) []any {
|
|
||||||
url := "https://gubatopic.eastmoney.com/interface/GetData.aspx?path=newtopic/api/Topic/HomePageListRead"
|
|
||||||
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
|
||||||
SetHeader("Host", "gubatopic.eastmoney.com").
|
|
||||||
SetHeader("Origin", "https://gubatopic.eastmoney.com").
|
|
||||||
SetHeader("Referer", "https://gubatopic.eastmoney.com/").
|
|
||||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
|
||||||
SetFormData(map[string]string{
|
|
||||||
"param": fmt.Sprintf("ps=%d&p=1&type=0", size),
|
|
||||||
"path": "newtopic/api/Topic/HomePageListRead",
|
|
||||||
"env": "2",
|
|
||||||
}).
|
|
||||||
Post(url)
|
|
||||||
if err != nil {
|
|
||||||
logger.SugaredLogger.Errorf("HotTopic err:%s", err.Error())
|
|
||||||
return []any{}
|
|
||||||
}
|
|
||||||
//logger.SugaredLogger.Infof("HotTopic:%s", resp.Body())
|
|
||||||
respMap := map[string]any{}
|
|
||||||
err = json.Unmarshal(resp.Body(), &respMap)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,6 @@ package data
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/coocood/freecache"
|
|
||||||
"go-stock/backend/db"
|
"go-stock/backend/db"
|
||||||
"go-stock/backend/logger"
|
"go-stock/backend/logger"
|
||||||
"testing"
|
"testing"
|
||||||
@ -37,7 +36,7 @@ func TestGetIndustryRank(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestGetIndustryMoneyRankSina(t *testing.T) {
|
func TestGetIndustryMoneyRankSina(t *testing.T) {
|
||||||
res := NewMarketNewsApi().GetIndustryMoneyRankSina("0", "netamount")
|
res := NewMarketNewsApi().GetIndustryMoneyRankSina("2")
|
||||||
for i, re := range res {
|
for i, re := range res {
|
||||||
logger.SugaredLogger.Debugf("key: %+v, value: %+v", i, re)
|
logger.SugaredLogger.Debugf("key: %+v, value: %+v", i, re)
|
||||||
|
|
||||||
@ -47,107 +46,6 @@ func TestGetMoneyRankSina(t *testing.T) {
|
|||||||
res := NewMarketNewsApi().GetMoneyRankSina("r3_net")
|
res := NewMarketNewsApi().GetMoneyRankSina("r3_net")
|
||||||
for i, re := range res {
|
for i, re := range res {
|
||||||
logger.SugaredLogger.Debugf("key: %+v, value: %+v", i, re)
|
logger.SugaredLogger.Debugf("key: %+v, value: %+v", i, re)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetStockMoneyTrendByDay(t *testing.T) {
|
|
||||||
res := NewMarketNewsApi().GetStockMoneyTrendByDay("sh600438", 360)
|
|
||||||
for i, re := range res {
|
|
||||||
logger.SugaredLogger.Debugf("key: %+v, value: %+v", i, re)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func TestTopStocksRankingList(t *testing.T) {
|
|
||||||
NewMarketNewsApi().TopStocksRankingList("2025-05-19")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLongTiger(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
|
|
||||||
NewMarketNewsApi().LongTiger("2025-06-08")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStockResearchReport(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
resp := NewMarketNewsApi().StockResearchReport("600584.sh", 7)
|
|
||||||
for _, a := range resp {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIndustryResearchReport(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
resp := NewMarketNewsApi().IndustryResearchReport("", 7)
|
|
||||||
for _, a := range resp {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStockNotice(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
resp := NewMarketNewsApi().StockNotice("600584,600900")
|
|
||||||
for _, a := range resp {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEMDictCode(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
resp := NewMarketNewsApi().EMDictCode("016", freecache.NewCache(100))
|
|
||||||
for _, a := range resp {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTradingViewNews(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
resp := NewMarketNewsApi().TradingViewNews()
|
|
||||||
for _, a := range *resp {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestXUEQIUHotStock(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
res := NewMarketNewsApi().XUEQIUHotStock(50, "10")
|
|
||||||
for _, a := range *res {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHotEvent(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
res := NewMarketNewsApi().HotEvent(50)
|
|
||||||
for _, a := range *res {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHotTopic(t *testing.T) {
|
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
res := NewMarketNewsApi().HotTopic(10)
|
|
||||||
for _, a := range res {
|
|
||||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ func (o OpenAi) NewSummaryStockNewsStream(userQuestion string, sysPromptId *int)
|
|||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
news := NewMarketNewsApi().GetNewsList("", 100)
|
news := NewMarketNewsApi().GetNewsList("财联社电报", 100)
|
||||||
messageText := strings.Builder{}
|
messageText := strings.Builder{}
|
||||||
for _, telegraph := range *news {
|
for _, telegraph := range *news {
|
||||||
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
|
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
|
||||||
@ -849,6 +849,6 @@ func (o OpenAi) SaveAIResponseResult(stockCode, stockName, result, chatId, quest
|
|||||||
|
|
||||||
func (o OpenAi) GetAIResponseResult(stock string) *models.AIResponseResult {
|
func (o OpenAi) GetAIResponseResult(stock string) *models.AIResponseResult {
|
||||||
var result models.AIResponseResult
|
var result models.AIResponseResult
|
||||||
db.Dao.Where("stock_code = ?", stock).Order("id desc").Limit(1).Find(&result)
|
db.Dao.Where("stock_code = ?", stock).Order("id desc").Limit(1).First(&result)
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,11 @@ func TestNewDeepSeekOpenAiConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTopNewsList(t *testing.T) {
|
func TestGetTopNewsList(t *testing.T) {
|
||||||
news := GetTopNewsList(30)
|
GetTopNewsList(30)
|
||||||
t.Log(news)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchGuShiTongStockInfo(t *testing.T) {
|
func TestSearchGuShiTongStockInfo(t *testing.T) {
|
||||||
db.Init("../../data/stock.db")
|
//db.Init("../../data/stock.db")
|
||||||
SearchGuShiTongStockInfo("hk01810", 60)
|
SearchGuShiTongStockInfo("hk01810", 60)
|
||||||
SearchGuShiTongStockInfo("sh600745", 60)
|
SearchGuShiTongStockInfo("sh600745", 60)
|
||||||
SearchGuShiTongStockInfo("gb_goog", 60)
|
SearchGuShiTongStockInfo("gb_goog", 60)
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
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)
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
@ -34,7 +34,6 @@ type Settings struct {
|
|||||||
DarkTheme bool `json:"darkTheme"`
|
DarkTheme bool `json:"darkTheme"`
|
||||||
BrowserPoolSize int `json:"browserPoolSize"`
|
BrowserPoolSize int `json:"browserPoolSize"`
|
||||||
EnableFund bool `json:"enableFund"`
|
EnableFund bool `json:"enableFund"`
|
||||||
EnablePushNews bool `json:"enablePushNews"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver Settings) TableName() string {
|
func (receiver Settings) TableName() string {
|
||||||
@ -79,7 +78,6 @@ func (s SettingsApi) UpdateConfig() string {
|
|||||||
"enable_news": s.Config.EnableNews,
|
"enable_news": s.Config.EnableNews,
|
||||||
"dark_theme": s.Config.DarkTheme,
|
"dark_theme": s.Config.DarkTheme,
|
||||||
"enable_fund": s.Config.EnableFund,
|
"enable_fund": s.Config.EnableFund,
|
||||||
"enable_push_news": s.Config.EnablePushNews,
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
|
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
|
||||||
@ -107,7 +105,6 @@ func (s SettingsApi) UpdateConfig() string {
|
|||||||
EnableNews: s.Config.EnableNews,
|
EnableNews: s.Config.EnableNews,
|
||||||
DarkTheme: s.Config.DarkTheme,
|
DarkTheme: s.Config.DarkTheme,
|
||||||
EnableFund: s.Config.EnableFund,
|
EnableFund: s.Config.EnableFund,
|
||||||
EnablePushNews: s.Config.EnablePushNews,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return "保存成功!"
|
return "保存成功!"
|
||||||
|
File diff suppressed because one or more lines are too long
@ -26,7 +26,6 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/plugin/soft_delete"
|
"gorm.io/plugin/soft_delete"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -248,7 +247,7 @@ func (receiver StockDataApi) GetIndexBasic() {
|
|||||||
func (receiver StockDataApi) GetStockBaseInfo() {
|
func (receiver StockDataApi) GetStockBaseInfo() {
|
||||||
res := &TushareStockBasicResponse{}
|
res := &TushareStockBasicResponse{}
|
||||||
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"
|
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"
|
||||||
resp, err := receiver.client.R().
|
_, err := receiver.client.R().
|
||||||
SetHeader("content-type", "application/json").
|
SetHeader("content-type", "application/json").
|
||||||
SetBody(&TushareRequest{
|
SetBody(&TushareRequest{
|
||||||
ApiName: "stock_basic",
|
ApiName: "stock_basic",
|
||||||
@ -259,7 +258,8 @@ func (receiver StockDataApi) GetStockBaseInfo() {
|
|||||||
SetResult(res).
|
SetResult(res).
|
||||||
Post(tushareApiUrl)
|
Post(tushareApiUrl)
|
||||||
//logger.SugaredLogger.Infof("GetStockBaseInfo %s", string(resp.Body()))
|
//logger.SugaredLogger.Infof("GetStockBaseInfo %s", string(resp.Body()))
|
||||||
ioutil.WriteFile("stock_basic.json", resp.Body(), 0666)
|
//resp.Body()写入文件
|
||||||
|
//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())
|
||||||
@ -400,20 +400,7 @@ func (receiver StockDataApi) Follow(stockCode string) string {
|
|||||||
logger.SugaredLogger.Error(err)
|
logger.SugaredLogger.Error(err)
|
||||||
return "关注失败"
|
return "关注失败"
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(stockCode, "us") {
|
|
||||||
stockCode = strings.Replace(stockCode, "us", "gb_", 1)
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(stockCode, "US") {
|
|
||||||
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)
|
|
||||||
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)
|
||||||
|
|
||||||
@ -476,64 +463,15 @@ func (receiver StockDataApi) SetAlarmChangePercent(val, alarmPrice float64, stoc
|
|||||||
return "设置成功"
|
return "设置成功"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) SetStockSort(newSort int64, stockCode string) {
|
func (receiver StockDataApi) SetStockSort(sort int64, stockCode string) {
|
||||||
//if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||||
// stockCode = strings.ToLower(stockCode)
|
stockCode = strings.ToLower(stockCode)
|
||||||
// stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||||
//}
|
|
||||||
|
|
||||||
// 获取当前排序值
|
|
||||||
var currentStock FollowedStock
|
|
||||||
if err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", strings.ToLower(stockCode)).First(¤tStock).Error; err != nil {
|
|
||||||
logger.SugaredLogger.Error("找不到当前股票: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", strings.ToLower(stockCode)).Update("sort", sort).Error
|
||||||
oldSort := currentStock.Sort
|
if err != nil {
|
||||||
|
logger.SugaredLogger.Error(err.Error())
|
||||||
// 如果排序值没有变化,直接返回
|
|
||||||
if oldSort == newSort {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// 检查新排序位置是否被占用
|
|
||||||
var count int64
|
|
||||||
if err := db.Dao.Model(&FollowedStock{}).Where("sort = ?", newSort).Count(&count).Error; err != nil {
|
|
||||||
logger.SugaredLogger.Error("检查新排序位置被占用失败: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if count == 0 {
|
|
||||||
// 新位置未被占用,直接更新当前记录
|
|
||||||
if err := db.Dao.Model(&FollowedStock{}).
|
|
||||||
Where("stock_code = ?", strings.ToLower(stockCode)).
|
|
||||||
Update("sort", newSort).Error; err != nil {
|
|
||||||
logger.SugaredLogger.Error("更新排序位置失败: ", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 新位置已被占用,需要移动其他记录
|
|
||||||
if newSort < oldSort {
|
|
||||||
// 向前移动:将中间记录向后移动
|
|
||||||
if err := db.Dao.Model(&FollowedStock{}).
|
|
||||||
Where("sort >= ? AND sort < ?", newSort, oldSort).
|
|
||||||
Update("sort", gorm.Expr("sort + 1")).Error; err != nil {
|
|
||||||
logger.SugaredLogger.Error("向前排序更新失败: ", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 向后移动:将中间记录向前移动
|
|
||||||
if err := db.Dao.Model(&FollowedStock{}).
|
|
||||||
Where("sort > ? AND sort <= ?", oldSort, newSort).
|
|
||||||
Update("sort", gorm.Expr("sort - 1")).Error; err != nil {
|
|
||||||
logger.SugaredLogger.Error("向后排序更新失败: ", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新目标记录的排序
|
|
||||||
if err := db.Dao.Model(&FollowedStock{}).
|
|
||||||
Where("stock_code = ?", strings.ToLower(stockCode)).
|
|
||||||
Update("sort", newSort).Error; err != nil {
|
|
||||||
logger.SugaredLogger.Error("更新股票排序失败: ", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
func (receiver StockDataApi) SetStockAICron(cron string, stockCode string) {
|
func (receiver StockDataApi) SetStockAICron(cron string, stockCode string) {
|
||||||
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||||
|
@ -47,7 +47,6 @@ func TestGetFinancialReports(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTelegraphSearch(t *testing.T) {
|
func TestGetTelegraphSearch(t *testing.T) {
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
//url := "https://www.cls.cn/searchPage?keyword=%E9%97%BB%E6%B3%B0%E7%A7%91%E6%8A%80&type=telegram"
|
//url := "https://www.cls.cn/searchPage?keyword=%E9%97%BB%E6%B3%B0%E7%A7%91%E6%8A%80&type=telegram"
|
||||||
messages := SearchStockInfo("谷歌", "telegram", 30)
|
messages := SearchStockInfo("谷歌", "telegram", 30)
|
||||||
for _, message := range *messages {
|
for _, message := range *messages {
|
||||||
@ -57,17 +56,16 @@ func TestGetTelegraphSearch(t *testing.T) {
|
|||||||
//https://www.cls.cn/stock?code=sh600745
|
//https://www.cls.cn/stock?code=sh600745
|
||||||
}
|
}
|
||||||
func TestSearchStockInfoByCode(t *testing.T) {
|
func TestSearchStockInfoByCode(t *testing.T) {
|
||||||
db.Init("../../data/stock.db")
|
|
||||||
SearchStockInfoByCode("sh600745")
|
SearchStockInfoByCode("sh600745")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchStockPriceInfo(t *testing.T) {
|
func TestSearchStockPriceInfo(t *testing.T) {
|
||||||
db.Init("../../data/stock.db")
|
db.Init("../../data/stock.db")
|
||||||
//SearchStockPriceInfo("中信证券", "hk06030", 30)
|
//SearchStockPriceInfo("中信证券", "hk06030", 30)
|
||||||
SearchStockPriceInfo("上海贝岭", "sh600171", 30)
|
//SearchStockPriceInfo("上海贝岭", "sh600171", 30)
|
||||||
//SearchStockPriceInfo("苹果公司", "gb_aapl", 30)
|
SearchStockPriceInfo("苹果公司", "gb_aapl", 30)
|
||||||
//SearchStockPriceInfo("微创光电", "bj430198", 30)
|
//SearchStockPriceInfo("微创光电", "bj430198", 30)
|
||||||
//getZSInfo("创业板指数", "sz399006", 30)
|
getZSInfo("创业板指数", "sz399006", 30)
|
||||||
//getZSInfo("上证综合指数", "sh000001", 30)
|
//getZSInfo("上证综合指数", "sh000001", 30)
|
||||||
//getZSInfo("沪深300指数", "sh000300", 30)
|
//getZSInfo("沪深300指数", "sh000300", 30)
|
||||||
|
|
||||||
|
@ -1,290 +0,0 @@
|
|||||||
package data
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"github.com/go-ego/gse"
|
|
||||||
"go-stock/backend/logger"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 金融情感词典,包含股票市场相关的专业词汇
|
|
||||||
var (
|
|
||||||
seg gse.Segmenter
|
|
||||||
|
|
||||||
// 正面金融词汇及其权重
|
|
||||||
positiveFinanceWords = map[string]float64{
|
|
||||||
"上涨": 2.0, "涨停": 3.0, "牛市": 3.0, "反弹": 2.0, "新高": 2.5,
|
|
||||||
"利好": 2.5, "增持": 2.0, "买入": 2.0, "推荐": 1.5, "看多": 2.0,
|
|
||||||
"盈利": 2.0, "增长": 2.0, "超预期": 2.5, "强劲": 1.5, "回升": 1.5,
|
|
||||||
"复苏": 2.0, "突破": 2.0, "创新高": 3.0, "回暖": 1.5, "上扬": 1.5,
|
|
||||||
"利好消息": 3.0, "收益增长": 2.5, "利润增长": 2.5, "业绩优异": 2.5,
|
|
||||||
"潜力股": 2.0, "绩优股": 2.0, "强势": 1.5, "走高": 1.5, "攀升": 1.5,
|
|
||||||
"大涨": 2.5, "飙升": 3.0, "井喷": 3.0, "爆发": 2.5, "暴涨": 3.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 负面金融词汇及其权重
|
|
||||||
negativeFinanceWords = map[string]float64{
|
|
||||||
"下跌": 2.0, "跌停": 3.0, "熊市": 3.0, "回调": 1.5, "新低": 2.5,
|
|
||||||
"利空": 2.5, "减持": 2.0, "卖出": 2.0, "看空": 2.0, "亏损": 2.5,
|
|
||||||
"下滑": 2.0, "萎缩": 2.0, "不及预期": 2.5, "疲软": 1.5, "恶化": 2.0,
|
|
||||||
"衰退": 2.0, "跌破": 2.0, "创新低": 3.0, "走弱": 1.5, "下挫": 1.5,
|
|
||||||
"利空消息": 3.0, "收益下降": 2.5, "利润下滑": 2.5, "业绩不佳": 2.5,
|
|
||||||
"垃圾股": 2.0, "风险股": 2.0, "弱势": 1.5, "走低": 1.5, "缩量": 2.5,
|
|
||||||
"大跌": 2.5, "暴跌": 3.0, "崩盘": 3.0, "跳水": 3.0, "重挫": 3.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 否定词,用于反转情感极性
|
|
||||||
negationWords = map[string]struct{}{
|
|
||||||
"不": {}, "没": {}, "无": {}, "非": {}, "未": {}, "别": {}, "勿": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 程度副词,用于调整情感强度
|
|
||||||
degreeWords = map[string]float64{
|
|
||||||
"非常": 1.8, "极其": 2.2, "太": 1.8, "很": 1.5,
|
|
||||||
"比较": 0.8, "稍微": 0.6, "有点": 0.7, "显著": 1.5,
|
|
||||||
"大幅": 1.8, "急剧": 2.0, "轻微": 0.6, "小幅": 0.7,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转折词,用于识别情感转折
|
|
||||||
transitionWords = map[string]struct{}{
|
|
||||||
"但是": {}, "然而": {}, "不过": {}, "却": {}, "可是": {},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// 加载默认词典
|
|
||||||
err := seg.LoadDict()
|
|
||||||
if err != nil {
|
|
||||||
logger.SugaredLogger.Error(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SentimentResult 情感分析结果类型
|
|
||||||
type SentimentResult struct {
|
|
||||||
Score float64 // 情感得分
|
|
||||||
Category SentimentType // 情感类别
|
|
||||||
PositiveCount int // 正面词数量
|
|
||||||
NegativeCount int // 负面词数量
|
|
||||||
Description string // 情感描述
|
|
||||||
}
|
|
||||||
|
|
||||||
// SentimentType 情感类型枚举
|
|
||||||
type SentimentType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
Positive SentimentType = iota
|
|
||||||
Negative
|
|
||||||
Neutral
|
|
||||||
)
|
|
||||||
|
|
||||||
// AnalyzeSentiment 判断文本的情感
|
|
||||||
func AnalyzeSentiment(text string) SentimentResult {
|
|
||||||
// 初始化得分
|
|
||||||
score := 0.0
|
|
||||||
positiveCount := 0
|
|
||||||
negativeCount := 0
|
|
||||||
|
|
||||||
// 分词(简单按单个字符分割)
|
|
||||||
words := splitWords(text)
|
|
||||||
|
|
||||||
// 检查文本是否包含转折词,并分割成两部分
|
|
||||||
var transitionIndex int
|
|
||||||
var hasTransition bool
|
|
||||||
for i, word := range words {
|
|
||||||
if _, ok := transitionWords[word]; ok {
|
|
||||||
transitionIndex = i
|
|
||||||
hasTransition = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理有转折的文本
|
|
||||||
if hasTransition {
|
|
||||||
// 转折前的部分
|
|
||||||
preTransitionWords := words[:transitionIndex]
|
|
||||||
preScore, prePos, preNeg := calculateScore(preTransitionWords)
|
|
||||||
|
|
||||||
// 转折后的部分,权重加倍
|
|
||||||
postTransitionWords := words[transitionIndex+1:]
|
|
||||||
postScore, postPos, postNeg := calculateScore(postTransitionWords)
|
|
||||||
postScore *= 1.5 // 转折后的情感更重要
|
|
||||||
|
|
||||||
score = preScore + postScore
|
|
||||||
positiveCount = prePos + postPos
|
|
||||||
negativeCount = preNeg + postNeg
|
|
||||||
} else {
|
|
||||||
// 没有转折的文本
|
|
||||||
score, positiveCount, negativeCount = calculateScore(words)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确定情感类别
|
|
||||||
var category SentimentType
|
|
||||||
switch {
|
|
||||||
case score > 1.0:
|
|
||||||
category = Positive
|
|
||||||
case score < -1.0:
|
|
||||||
category = Negative
|
|
||||||
default:
|
|
||||||
category = Neutral
|
|
||||||
}
|
|
||||||
|
|
||||||
return SentimentResult{
|
|
||||||
Score: score,
|
|
||||||
Category: category,
|
|
||||||
PositiveCount: positiveCount,
|
|
||||||
NegativeCount: negativeCount,
|
|
||||||
Description: GetSentimentDescription(category),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算情感得分
|
|
||||||
func calculateScore(words []string) (float64, int, int) {
|
|
||||||
score := 0.0
|
|
||||||
positiveCount := 0
|
|
||||||
negativeCount := 0
|
|
||||||
|
|
||||||
// 遍历每个词,计算情感得分
|
|
||||||
for i, word := range words {
|
|
||||||
// 首先检查是否为程度副词
|
|
||||||
degree, isDegree := degreeWords[word]
|
|
||||||
|
|
||||||
// 检查是否为否定词
|
|
||||||
_, isNegation := negationWords[word]
|
|
||||||
|
|
||||||
// 检查是否为金融正面词
|
|
||||||
if posScore, isPositive := positiveFinanceWords[word]; isPositive {
|
|
||||||
// 检查前一个词是否为否定词或程度副词
|
|
||||||
if i > 0 {
|
|
||||||
prevWord := words[i-1]
|
|
||||||
if _, isNeg := negationWords[prevWord]; isNeg {
|
|
||||||
score -= posScore
|
|
||||||
negativeCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if deg, isDeg := degreeWords[prevWord]; isDeg {
|
|
||||||
score += posScore * deg
|
|
||||||
positiveCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
score += posScore
|
|
||||||
positiveCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否为金融负面词
|
|
||||||
if negScore, isNegative := negativeFinanceWords[word]; isNegative {
|
|
||||||
// 检查前一个词是否为否定词或程度副词
|
|
||||||
if i > 0 {
|
|
||||||
prevWord := words[i-1]
|
|
||||||
if _, isNeg := negationWords[prevWord]; isNeg {
|
|
||||||
score += negScore
|
|
||||||
positiveCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if deg, isDeg := degreeWords[prevWord]; isDeg {
|
|
||||||
score -= negScore * deg
|
|
||||||
negativeCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
score -= negScore
|
|
||||||
negativeCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理程度副词(如果后面跟着情感词)
|
|
||||||
if isDegree && i+1 < len(words) {
|
|
||||||
nextWord := words[i+1]
|
|
||||||
|
|
||||||
if posScore, isPositive := positiveFinanceWords[nextWord]; isPositive {
|
|
||||||
score += posScore * degree
|
|
||||||
positiveCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if negScore, isNegative := negativeFinanceWords[nextWord]; isNegative {
|
|
||||||
score -= negScore * degree
|
|
||||||
negativeCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理否定词(如果后面跟着情感词)
|
|
||||||
if isNegation && i+1 < len(words) {
|
|
||||||
nextWord := words[i+1]
|
|
||||||
|
|
||||||
if posScore, isPositive := positiveFinanceWords[nextWord]; isPositive {
|
|
||||||
score -= posScore
|
|
||||||
negativeCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if negScore, isNegative := negativeFinanceWords[nextWord]; isNegative {
|
|
||||||
score += negScore
|
|
||||||
positiveCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return score, positiveCount, negativeCount
|
|
||||||
}
|
|
||||||
|
|
||||||
// 简单的分词函数,考虑了中文和英文
|
|
||||||
func splitWords(text string) []string {
|
|
||||||
return seg.Cut(text, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSentimentDescription 获取情感类别的文本描述
|
|
||||||
func GetSentimentDescription(category SentimentType) string {
|
|
||||||
switch category {
|
|
||||||
case Positive:
|
|
||||||
return "看涨"
|
|
||||||
case Negative:
|
|
||||||
return "看跌"
|
|
||||||
case Neutral:
|
|
||||||
return "中性"
|
|
||||||
default:
|
|
||||||
return "未知"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// 从命令行读取输入
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
fmt.Println("请输入要分析的股市相关文本(输入exit退出):")
|
|
||||||
|
|
||||||
for {
|
|
||||||
fmt.Print("> ")
|
|
||||||
text, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("读取输入时出错:", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 去除换行符
|
|
||||||
text = strings.TrimSpace(text)
|
|
||||||
|
|
||||||
// 检查是否退出
|
|
||||||
if text == "exit" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分析情感
|
|
||||||
result := AnalyzeSentiment(text)
|
|
||||||
|
|
||||||
// 输出结果
|
|
||||||
fmt.Printf("情感分析结果: %s (得分: %.2f, 正面词:%d, 负面词:%d)\n",
|
|
||||||
GetSentimentDescription(result.Category),
|
|
||||||
result.Score,
|
|
||||||
result.PositiveCount,
|
|
||||||
result.NegativeCount)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package data
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @Author spark
|
|
||||||
// @Date 2025/6/19 13:05
|
|
||||||
// @Desc
|
|
||||||
//-----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func TestAnalyzeSentiment(t *testing.T) {
|
|
||||||
// 分析情感
|
|
||||||
text := " 【调查:韩国近两成中小学生过度使用智能手机或互联网】财联社6月19日电,韩国女性家族部18日公布的一项年度调查结果显示,接受调查的韩国中小学生中,共计约17.3%、即超过21万人使用智能手机或互联网的程度达到了“危险水平”,这意味着他们因过度依赖智能手机或互联网而需要关注或干预,这一比例引人担忧。 (新华社)\n"
|
|
||||||
text = "消息人士称,联合利华(Unilever)正在为Graze零食品牌寻找买家。\n"
|
|
||||||
text = "【韩国未来5年将投入51万亿韩元发展文化产业】 据韩联社,韩国文化体育观光部(文体部)今后5年将投入51万亿韩元(约合人民币2667亿元)预算,落实总统李在明在竞选时期提出的“将韩国打造成全球五大文化强国之一”的承诺。\n"
|
|
||||||
//text = "【油气股持续拉升 国际实业午后涨停】财联社6月19日电,油气股午后持续拉升,国际实业、宝莫股份午后涨停,准油股份、山东墨龙。茂化实华此前涨停,通源石油、海默科技、贝肯能源、中曼石油、科力股份等多股涨超5%。\n"
|
|
||||||
//text = " 【三大指数均跌逾1% 下跌个股近4800只】财联社6月19日电,指数持续走弱,沪指下挫跌逾1.00%,深成指跌1.25%,创业板指跌1.39%。核聚变、风电、军工、食品消费等板块指数跌幅居前,沪深京三市下跌个股近4800只。\n"
|
|
||||||
text = "【银行理财首单网下打新落地】财联社6月20日电,记者从多渠道获悉,光大理财以申报价格17元参与信通电子网下打新,并成功入围有效报价,成为行业内首家参与网下打新的银行理财公司。光大理财工作人员向证券时报记者表示,本次光大理财是以其管理的混合类产品“阳光橙增盈绝对收益策略”参与了此次网下打新,该产品为光大理财“固收+”银行理财产品。资料显示,信通电子成立于1996年,核心产品包括输电线路智能巡检系统、变电站智能辅控系统、移动智能终端及其他产品。根据其招股说明书,信通电子2023、2024年营业收入分别较上年增长19.08%和7.97%,净利润分别较上年增长5.6%和15.11%。 (证券时报)"
|
|
||||||
text = " 【以军称拦截数枚伊朗导弹】财联社6月20日电,据央视新闻报道,以军在贝尔谢巴及周边区域拦截了数枚伊朗导弹,但仍有导弹或拦截残骸落地。以色列国防军发文表示,搜救队伍正在一处“空中物体落地”的所在区域开展工作,公众目前可以离开避难场所。伊朗方面对上述说法暂无回应。"
|
|
||||||
|
|
||||||
words := splitWords(text)
|
|
||||||
fmt.Println(strings.Join(words, " "))
|
|
||||||
|
|
||||||
result := AnalyzeSentiment(text)
|
|
||||||
|
|
||||||
// 输出结果
|
|
||||||
fmt.Printf("情感分析结果: %s (得分: %.2f, 正面词:%d, 负面词:%d)\n",
|
|
||||||
result.Description,
|
|
||||||
result.Score,
|
|
||||||
result.PositiveCount,
|
|
||||||
result.NegativeCount)
|
|
||||||
|
|
||||||
}
|
|
@ -226,7 +226,6 @@ type Telegraph struct {
|
|||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
TelegraphTags []TelegraphTags `json:"tags" gorm:"-:migration;foreignKey:TelegraphId"`
|
TelegraphTags []TelegraphTags `json:"tags" gorm:"-:migration;foreignKey:TelegraphId"`
|
||||||
SentimentResult string `json:"sentimentResult" gorm:"-:all"`
|
|
||||||
}
|
}
|
||||||
type TelegraphTags struct {
|
type TelegraphTags struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
@ -278,87 +277,3 @@ type SinaStockInfo struct {
|
|||||||
MarketValue string `json:"market_value"`
|
MarketValue string `json:"market_value"`
|
||||||
PeRatio string `json:"pe_ratio"`
|
PeRatio string `json:"pe_ratio"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LongTigerRankData struct {
|
|
||||||
ACCUMAMOUNT float64 `json:"ACCUM_AMOUNT"`
|
|
||||||
BILLBOARDBUYAMT float64 `json:"BILLBOARD_BUY_AMT"`
|
|
||||||
BILLBOARDDEALAMT float64 `json:"BILLBOARD_DEAL_AMT"`
|
|
||||||
BILLBOARDNETAMT float64 `json:"BILLBOARD_NET_AMT"`
|
|
||||||
BILLBOARDSELLAMT float64 `json:"BILLBOARD_SELL_AMT"`
|
|
||||||
CHANGERATE float64 `json:"CHANGE_RATE"`
|
|
||||||
CLOSEPRICE float64 `json:"CLOSE_PRICE"`
|
|
||||||
DEALAMOUNTRATIO float64 `json:"DEAL_AMOUNT_RATIO"`
|
|
||||||
DEALNETRATIO float64 `json:"DEAL_NET_RATIO"`
|
|
||||||
EXPLAIN string `json:"EXPLAIN"`
|
|
||||||
EXPLANATION string `json:"EXPLANATION"`
|
|
||||||
FREEMARKETCAP float64 `json:"FREE_MARKET_CAP"`
|
|
||||||
SECUCODE string `json:"SECUCODE" gorm:"index"`
|
|
||||||
SECURITYCODE string `json:"SECURITY_CODE"`
|
|
||||||
SECURITYNAMEABBR string `json:"SECURITY_NAME_ABBR"`
|
|
||||||
SECURITYTYPECODE string `json:"SECURITY_TYPE_CODE"`
|
|
||||||
TRADEDATE string `json:"TRADE_DATE" gorm:"index"`
|
|
||||||
TURNOVERRATE float64 `json:"TURNOVERRATE"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l LongTigerRankData) TableName() string {
|
|
||||||
return "long_tiger_rank"
|
|
||||||
}
|
|
||||||
|
|
||||||
type TVNews struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Published int `json:"published"`
|
|
||||||
Urgency int `json:"urgency"`
|
|
||||||
Permission string `json:"permission"`
|
|
||||||
StoryPath string `json:"storyPath"`
|
|
||||||
Provider struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
LogoId string `json:"logo_id"`
|
|
||||||
} `json:"provider"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type XUEQIUHot struct {
|
|
||||||
Data struct {
|
|
||||||
Items []HotItem `json:"items"`
|
|
||||||
ItemsSize int `json:"items_size"`
|
|
||||||
} `json:"data"`
|
|
||||||
ErrorCode int `json:"error_code"`
|
|
||||||
ErrorDescription string `json:"error_description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HotItem struct {
|
|
||||||
Type int `json:"type"`
|
|
||||||
Code string `json:"code"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Value float64 `json:"value"`
|
|
||||||
Increment int `json:"increment"`
|
|
||||||
RankChange int `json:"rank_change"`
|
|
||||||
HasExist interface{} `json:"has_exist"`
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
Percent float64 `json:"percent"`
|
|
||||||
Current float64 `json:"current"`
|
|
||||||
Chg float64 `json:"chg"`
|
|
||||||
Exchange string `json:"exchange"`
|
|
||||||
StockType int `json:"stock_type"`
|
|
||||||
SubType string `json:"sub_type"`
|
|
||||||
Ad int `json:"ad"`
|
|
||||||
AdId interface{} `json:"ad_id"`
|
|
||||||
ContentId interface{} `json:"content_id"`
|
|
||||||
Page interface{} `json:"page"`
|
|
||||||
Model interface{} `json:"model"`
|
|
||||||
Location interface{} `json:"location"`
|
|
||||||
TradeSession interface{} `json:"trade_session"`
|
|
||||||
CurrentExt interface{} `json:"current_ext"`
|
|
||||||
PercentExt interface{} `json:"percent_ext"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HotEvent struct {
|
|
||||||
PicSize interface{} `json:"pic_size"`
|
|
||||||
Tag string `json:"tag"`
|
|
||||||
Id int `json:"id"`
|
|
||||||
Pic string `json:"pic"`
|
|
||||||
Hot int `json:"hot"`
|
|
||||||
StatusCount int `json:"status_count"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
File diff suppressed because one or more lines are too long
673
frontend/package-lock.json
generated
673
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +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",
|
"@vicons/ionicons5": "^0.13.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",
|
||||||
@ -23,19 +23,11 @@
|
|||||||
"vue3-danmaku": "^1.6.1"
|
"vue3-danmaku": "^1.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vicons/antd": "^0.13.0",
|
|
||||||
"@vicons/carbon": "^0.13.0",
|
|
||||||
"@vicons/fa": "^0.13.0",
|
|
||||||
"@vicons/fluent": "^0.13.0",
|
|
||||||
"@vicons/ionicons4": "^0.13.0",
|
|
||||||
"@vicons/ionicons5": "^0.13.0",
|
|
||||||
"@vicons/material": "^0.13.0",
|
|
||||||
"@vicons/tabler": "^0.13.0",
|
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"html-docx-js-typescript": "^0.1.5",
|
"html-docx-js-typescript": "^0.1.5",
|
||||||
"naive-ui": "^2.41.0",
|
"naive-ui": "^2.41.0",
|
||||||
"vfonts": "^0.0.3",
|
"vfonts": "^0.0.3",
|
||||||
"vite": "^6.3.5"
|
"vite": "^5.4.12"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"AI赋能股票分析",
|
"AI赋能股票分析",
|
||||||
|
@ -1 +1 @@
|
|||||||
2d63c3a999d797889c01d6c96451b197
|
99aeae4d0e7cbe900b379d3e7d2f44d7
|
@ -1,50 +1,39 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
EventsEmit,
|
EventsEmit,
|
||||||
EventsOff,
|
|
||||||
EventsOn,
|
EventsOn,
|
||||||
Quit,
|
Quit,
|
||||||
WindowFullscreen,
|
WindowFullscreen, WindowGetPosition,
|
||||||
WindowHide,
|
WindowHide,
|
||||||
|
WindowSetPosition,
|
||||||
WindowUnfullscreen
|
WindowUnfullscreen
|
||||||
} from '../wailsjs/runtime'
|
} from '../wailsjs/runtime'
|
||||||
import {h, onBeforeMount, onBeforeUnmount, onMounted, ref} from "vue";
|
import {h, onBeforeMount, onMounted, ref} from "vue";
|
||||||
import {RouterLink, useRouter} from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
import {createDiscreteApi,darkTheme,lightTheme , NIcon, NText,dateZhCN,zhCN} from 'naive-ui'
|
import {darkTheme, NButton, NGradientText, NIcon, NText,} from 'naive-ui'
|
||||||
import {
|
import {
|
||||||
AlarmOutline,
|
SettingsOutline,
|
||||||
AnalyticsOutline,
|
|
||||||
BarChartSharp, Bonfire, BonfireOutline, EaselSharp,
|
|
||||||
ExpandOutline, Flag,
|
|
||||||
Flame, FlameSharp, InformationOutline,
|
|
||||||
LogoGithub,
|
|
||||||
NewspaperOutline,
|
|
||||||
NewspaperSharp, Notifications,
|
|
||||||
PowerOutline, Pulse,
|
|
||||||
ReorderTwoOutline,
|
ReorderTwoOutline,
|
||||||
SettingsOutline, Skull, SkullOutline, SkullSharp,
|
ExpandOutline,
|
||||||
SparklesOutline,
|
PowerOutline,
|
||||||
|
LogoGithub,
|
||||||
|
MoveOutline,
|
||||||
|
WalletOutline,
|
||||||
StarOutline,
|
StarOutline,
|
||||||
Wallet, WarningOutline,
|
AlarmOutline,
|
||||||
|
SparklesOutline,
|
||||||
|
NewspaperOutline,
|
||||||
|
AnalyticsOutline, BarChartSharp, NewspaperSharp, Flame, BarChartOutline, Wallet,
|
||||||
} from '@vicons/ionicons5'
|
} from '@vicons/ionicons5'
|
||||||
import {AnalyzeSentiment, GetConfig, GetGroupList} from "../wailsjs/go/main/App";
|
import {GetConfig, GetGroupList} from "../wailsjs/go/main/App";
|
||||||
import {Dragon, Fire, Gripfire} from "@vicons/fa";
|
import { useRouter } from 'vue-router'
|
||||||
import {ReportSearch} from "@vicons/tabler";
|
|
||||||
import {LocalFireDepartmentRound} from "@vicons/material";
|
|
||||||
import {BoxSearch20Regular, CommentNote20Filled} from "@vicons/fluent";
|
|
||||||
import {FireFilled, FireOutlined, NotificationFilled, StockOutlined} from "@vicons/antd";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loading = ref(true)
|
|
||||||
const loadingMsg = ref("加载数据中...")
|
|
||||||
const enableNews= ref(false)
|
const enableNews= ref(false)
|
||||||
const contentStyle = ref("")
|
const contentStyle = ref("")
|
||||||
const enableFund = ref(false)
|
const enableFund = ref(false)
|
||||||
const enableDarkTheme = ref(null)
|
const enableDarkTheme = ref(null)
|
||||||
const content = ref('数据来源于网络,仅供参考;投资有风险,入市需谨慎\n\n未经授权,禁止商业目的!')
|
const content = ref('数据来源于网络,仅供参考;投资有风险,入市需谨慎')
|
||||||
const isFullscreen = ref(false)
|
const isFullscreen = ref(false)
|
||||||
const activeKey = ref('')
|
const activeKey = ref('')
|
||||||
const containerRef= ref({})
|
const containerRef= ref({})
|
||||||
@ -63,7 +52,8 @@ const menuOptions = ref([
|
|||||||
groupName: '全部',
|
groupName: '全部',
|
||||||
groupId: 0,
|
groupId: 0,
|
||||||
},
|
},
|
||||||
params: {},
|
params: {
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ default: () => '股票自选',}
|
{ default: () => '股票自选',}
|
||||||
@ -111,7 +101,8 @@ const menuOptions = ref([
|
|||||||
href: '#',
|
href: '#',
|
||||||
to: {
|
to: {
|
||||||
name: 'market',
|
name: 'market',
|
||||||
params: {}
|
params: {
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onClick: ()=>{
|
onClick: ()=>{
|
||||||
EventsEmit("changeMarketTab", {ID:0,name:'市场快讯'})
|
EventsEmit("changeMarketTab", {ID:0,name:'市场快讯'})
|
||||||
@ -204,7 +195,7 @@ const menuOptions = ref([
|
|||||||
{ default: () => '行业排名',}
|
{ default: () => '行业排名',}
|
||||||
),
|
),
|
||||||
key: 'market4',
|
key: 'market4',
|
||||||
icon: renderIcon(Flag),
|
icon: renderIcon(Flame),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
@ -225,134 +216,8 @@ const menuOptions = ref([
|
|||||||
{ default: () => '个股资金流向',}
|
{ default: () => '个股资金流向',}
|
||||||
),
|
),
|
||||||
key: 'market5',
|
key: 'market5',
|
||||||
icon: renderIcon(Pulse),
|
icon: renderIcon(Wallet),
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () =>
|
|
||||||
h(
|
|
||||||
RouterLink,
|
|
||||||
{
|
|
||||||
href: '#',
|
|
||||||
to: {
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: "龙虎榜",
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
onClick: () => {
|
|
||||||
EventsEmit("changeMarketTab", {ID: 0, name: '龙虎榜'})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{default: () => '龙虎榜',}
|
|
||||||
),
|
|
||||||
key: 'market6',
|
|
||||||
icon: renderIcon(Dragon),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () =>
|
|
||||||
h(
|
|
||||||
RouterLink,
|
|
||||||
{
|
|
||||||
href: '#',
|
|
||||||
to: {
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: "个股研报",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick: () => {
|
|
||||||
EventsEmit("changeMarketTab", {ID: 0, name: '个股研报'})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{default: () => '个股研报',}
|
|
||||||
),
|
|
||||||
key: 'market7',
|
|
||||||
icon: renderIcon(StockOutlined),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () =>
|
|
||||||
h(
|
|
||||||
RouterLink,
|
|
||||||
{
|
|
||||||
href: '#',
|
|
||||||
to: {
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: "公司公告",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick: () => {
|
|
||||||
EventsEmit("changeMarketTab", {ID: 0, name: '公司公告'})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{default: () => '公司公告',}
|
|
||||||
),
|
|
||||||
key: 'market8',
|
|
||||||
icon: renderIcon(NotificationFilled),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () =>
|
|
||||||
h(
|
|
||||||
RouterLink,
|
|
||||||
{
|
|
||||||
href: '#',
|
|
||||||
to: {
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: "行业研究",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick: () => {
|
|
||||||
EventsEmit("changeMarketTab", {ID: 0, name: '行业研究'})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{default: () => '行业研究',}
|
|
||||||
),
|
|
||||||
key: 'market9',
|
|
||||||
icon: renderIcon(ReportSearch),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () =>
|
|
||||||
h(
|
|
||||||
RouterLink,
|
|
||||||
{
|
|
||||||
href: '#',
|
|
||||||
to: {
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: "当前热门",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick: () => {
|
|
||||||
EventsEmit("changeMarketTab", {ID: 0, name: '当前热门'})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{default: () => '当前热门',}
|
|
||||||
),
|
|
||||||
key: 'market10',
|
|
||||||
icon: renderIcon(Gripfire),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () =>
|
|
||||||
h(
|
|
||||||
RouterLink,
|
|
||||||
{
|
|
||||||
href: '#',
|
|
||||||
to: {
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: "指标选股",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick: () => {
|
|
||||||
EventsEmit("changeMarketTab", {ID: 0, name: '指标选股'})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{default: () => '指标选股',}
|
|
||||||
),
|
|
||||||
key: 'market11',
|
|
||||||
icon: renderIcon(BoxSearch20Regular),
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -362,7 +227,8 @@ const menuOptions = ref([
|
|||||||
{
|
{
|
||||||
to: {
|
to: {
|
||||||
name: 'fund',
|
name: 'fund',
|
||||||
params: {},
|
params: {
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ default: () => '基金自选',}
|
{ default: () => '基金自选',}
|
||||||
@ -386,7 +252,8 @@ const menuOptions = ref([
|
|||||||
{
|
{
|
||||||
to: {
|
to: {
|
||||||
name: 'settings',
|
name: 'settings',
|
||||||
params: {}
|
params: {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ default: () => '设置' }
|
{ default: () => '设置' }
|
||||||
@ -401,7 +268,8 @@ const menuOptions = ref([
|
|||||||
{
|
{
|
||||||
to: {
|
to: {
|
||||||
name: 'about',
|
name: 'about',
|
||||||
params: {}
|
params: {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ default: () => '关于' }
|
{ default: () => '关于' }
|
||||||
@ -445,11 +313,9 @@ const menuOptions = ref([
|
|||||||
icon: renderIcon(PowerOutline),
|
icon: renderIcon(PowerOutline),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
function renderIcon(icon) {
|
function renderIcon(icon) {
|
||||||
return () => h(NIcon, null, { default: () => h(icon) })
|
return () => h(NIcon, null, { default: () => h(icon) })
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFullscreen(e) {
|
function toggleFullscreen(e) {
|
||||||
//console.log(e)
|
//console.log(e)
|
||||||
if (isFullscreen.value) {
|
if (isFullscreen.value) {
|
||||||
@ -461,7 +327,6 @@ function toggleFullscreen(e) {
|
|||||||
}
|
}
|
||||||
isFullscreen.value=!isFullscreen.value
|
isFullscreen.value=!isFullscreen.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// const drag = ref(false)
|
// const drag = ref(false)
|
||||||
// const lastPos= ref({x:0,y:0})
|
// const lastPos= ref({x:0,y:0})
|
||||||
// function toggleStartMoveWindow(e) {
|
// function toggleStartMoveWindow(e) {
|
||||||
@ -486,24 +351,6 @@ EventsOn("telegraph", (data) => {
|
|||||||
telegraph.value=data
|
telegraph.value=data
|
||||||
})
|
})
|
||||||
|
|
||||||
EventsOn("loadingMsg", (data) => {
|
|
||||||
if(data==="done"){
|
|
||||||
loadingMsg.value = "加载完成..."
|
|
||||||
EventsEmit("loadingDone", "app")
|
|
||||||
loading.value = false
|
|
||||||
}else{
|
|
||||||
loading.value = true
|
|
||||||
loadingMsg.value = data
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
EventsOff("realtime_profit")
|
|
||||||
EventsOff("loadingMsg")
|
|
||||||
EventsOff("telegraph")
|
|
||||||
EventsOff("newsPush")
|
|
||||||
})
|
|
||||||
|
|
||||||
window.onerror = function (msg, source, lineno, colno, error) {
|
window.onerror = function (msg, source, lineno, colno, error) {
|
||||||
// 将错误信息发送给后端
|
// 将错误信息发送给后端
|
||||||
EventsEmit("frontendError", {
|
EventsEmit("frontendError", {
|
||||||
@ -562,6 +409,7 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GetConfig().then((res)=>{
|
GetConfig().then((res)=>{
|
||||||
//console.log(res)
|
//console.log(res)
|
||||||
enableFund.value=res.enableFund
|
enableFund.value=res.enableFund
|
||||||
@ -581,49 +429,23 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
contentStyle.value = "max-height: calc(92vh);overflow: hidden"
|
contentStyle.value="max-height: calc(90vh);overflow: hidden"
|
||||||
GetConfig().then((res)=>{
|
GetConfig().then((res)=>{
|
||||||
if(res.enableNews){
|
if(res.enableNews){
|
||||||
enableNews.value=true
|
enableNews.value=true
|
||||||
}
|
}
|
||||||
enableFund.value=res.enableFund
|
enableFund.value=res.enableFund
|
||||||
const {notification } =createDiscreteApi(["notification"], {
|
|
||||||
configProviderProps: {
|
|
||||||
theme: enableDarkTheme.value ? darkTheme : lightTheme ,
|
|
||||||
max: 3,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
EventsOn("newsPush", (data) => {
|
|
||||||
//console.log(data)
|
|
||||||
if(data.isRed){
|
|
||||||
notification.create({
|
|
||||||
//type:"error",
|
|
||||||
// avatar: () => h(NIcon,{component:Notifications,color:"red"}),
|
|
||||||
title: data.time,
|
|
||||||
content: () => h(NText,{type:"error"}, { default: () => data.content }),
|
|
||||||
meta: () => h(NText,{type:"warning"}, { default: () => data.source}),
|
|
||||||
duration:1000*40,
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
notification.create({
|
|
||||||
//type:"info",
|
|
||||||
//avatar: () => h(NIcon,{component:Notifications}),
|
|
||||||
title: data.time,
|
|
||||||
content: () => h(NText,{type:"info"}, { default: () => data.content }),
|
|
||||||
meta: () => h(NText,{type:"warning"}, { default: () => data.source}),
|
|
||||||
duration:1000*30 ,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<n-config-provider ref="containerRef" :theme="enableDarkTheme" :locale="zhCN" :date-locale="dateZhCN">
|
<n-config-provider ref="containerRef" :theme="enableDarkTheme" >
|
||||||
<n-message-provider >
|
<n-message-provider >
|
||||||
<n-notification-provider>
|
<n-notification-provider>
|
||||||
<n-modal-provider>
|
<n-modal-provider>
|
||||||
<n-dialog-provider>
|
<n-dialog-provider>
|
||||||
|
|
||||||
<n-watermark
|
<n-watermark
|
||||||
:content="content"
|
:content="content"
|
||||||
cross
|
cross
|
||||||
@ -638,23 +460,25 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
<n-flex>
|
<n-flex>
|
||||||
<n-grid x-gap="12" :cols="1">
|
<n-grid x-gap="12" :cols="1">
|
||||||
|
<!--
|
||||||
|
<n-gi style="position: relative;top:1px;z-index: 19;width: 100%" v-if="telegraph.length>0">
|
||||||
|
|
||||||
|
</n-gi>
|
||||||
|
-->
|
||||||
|
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<n-spin :show="loading">
|
<n-marquee :speed="100" style="position: relative;top:0;z-index: 19;width: 100%" v-if="(telegraph.length>0)&&(enableNews)">
|
||||||
<template #description>
|
|
||||||
{{ loadingMsg }}
|
|
||||||
</template>
|
|
||||||
<n-marquee :speed="100" style="position: relative;top:0;z-index: 19;width: 100%"
|
|
||||||
v-if="(telegraph.length>0)&&(enableNews)">
|
|
||||||
<n-tag type="warning" v-for="item in telegraph" style="margin-right: 10px">
|
<n-tag type="warning" v-for="item in telegraph" style="margin-right: 10px">
|
||||||
{{item}}
|
{{item}}
|
||||||
</n-tag>
|
</n-tag>
|
||||||
|
<!-- <n-text type="warning"> {{telegraph[0]}}</n-text>-->
|
||||||
</n-marquee>
|
</n-marquee>
|
||||||
<n-scrollbar :style="contentStyle">
|
<n-scrollbar :style="contentStyle">
|
||||||
<n-skeleton v-if="loading" height="calc(100vh)" />
|
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
</n-spin>
|
|
||||||
</n-gi>
|
</n-gi>
|
||||||
|
|
||||||
|
|
||||||
<n-gi style="position: fixed;bottom:0;z-index: 9;width: 100%;">
|
<n-gi style="position: fixed;bottom:0;z-index: 9;width: 100%;">
|
||||||
<n-card size="small" style="--wails-draggable:drag">
|
<n-card size="small" style="--wails-draggable:drag">
|
||||||
<n-menu style="font-size: 18px;"
|
<n-menu style="font-size: 18px;"
|
||||||
|
@ -1,102 +0,0 @@
|
|||||||
<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>
|
|
@ -1,37 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {onBeforeMount, onUnmounted, ref} from 'vue'
|
|
||||||
import {HotEvent} from "../../wailsjs/go/main/App";
|
|
||||||
const list = ref([])
|
|
||||||
|
|
||||||
const task =ref()
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
list.value = await HotEvent(50)
|
|
||||||
task.value=setInterval(async ()=>{
|
|
||||||
list.value = await HotEvent(50)
|
|
||||||
}, 1000*10)
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(async ()=>{
|
|
||||||
clearInterval(task.value)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-list bordered>
|
|
||||||
<template #header>
|
|
||||||
雪球热门
|
|
||||||
</template>
|
|
||||||
<n-list-item v-for="(item, index) in list" :key="index">
|
|
||||||
<n-thing :title="item.tag" :description="item.content" >
|
|
||||||
<template v-if="item.pic" #avatar>
|
|
||||||
<n-avatar :src="item.pic" :size="60">
|
|
||||||
</n-avatar>
|
|
||||||
</template>
|
|
||||||
</n-thing>
|
|
||||||
</n-list-item>
|
|
||||||
</n-list>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,88 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {onBeforeMount, onUnmounted, ref} from 'vue'
|
|
||||||
import {HotStock} from "../../wailsjs/go/main/App";
|
|
||||||
import KLineChart from "./KLineChart.vue";
|
|
||||||
import {ArrowBack, ArrowDown, ArrowUp} from "@vicons/ionicons5";
|
|
||||||
|
|
||||||
const {marketType}=defineProps(
|
|
||||||
{
|
|
||||||
marketType: {
|
|
||||||
type: String,
|
|
||||||
default: '10'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const task =ref()
|
|
||||||
|
|
||||||
const list = ref([])
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
list.value = await HotStock(marketType)
|
|
||||||
task.value = setInterval(async () => {
|
|
||||||
list.value = await HotStock(marketType)
|
|
||||||
}, 5000)
|
|
||||||
})
|
|
||||||
onUnmounted(()=>{
|
|
||||||
clearInterval(task.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
function getMarketCode(item) {
|
|
||||||
if (item.exchange === 'SZ') {
|
|
||||||
return item.code.toLowerCase()
|
|
||||||
}
|
|
||||||
if (item.exchange === 'SH') {
|
|
||||||
return item.code.toLowerCase()
|
|
||||||
}
|
|
||||||
if (item.exchange === 'HK') {
|
|
||||||
return (item.exchange + item.code).toLowerCase()
|
|
||||||
}
|
|
||||||
return ("gb_"+item.code).toLowerCase()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-table striped size="small">
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<n-th>股票名称</n-th>
|
|
||||||
<n-th>涨跌幅</n-th>
|
|
||||||
<n-th>当前价格</n-th>
|
|
||||||
<n-th>热度</n-th>
|
|
||||||
<n-th>热度变化</n-th>
|
|
||||||
<n-th>排名变化</n-th>
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="item in list" :key="item.code">
|
|
||||||
<n-td><n-text type="info">
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-tag type="info" :bordered="false"> {{item.name}} {{item.code}}</n-tag>
|
|
||||||
</template>
|
|
||||||
<k-line-chart style="width: 800px" :code="getMarketCode(item)" :chart-height="500" :name="item.name" :k-days="20" :dark-theme="true"></k-line-chart>
|
|
||||||
</n-popover>
|
|
||||||
</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.percent>0?'error':'success'">{{item.percent}}%</n-text></n-td>
|
|
||||||
<n-td><n-text type="info">{{item.current}}</n-text></n-td>
|
|
||||||
<n-td><n-text type="info">{{item.value}}</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.increment>0?'error':'success'">
|
|
||||||
{{item.increment}}
|
|
||||||
<n-icon v-if="item.increment>0" :component="ArrowUp"/>
|
|
||||||
<n-icon v-else :component="ArrowDown"/>
|
|
||||||
</n-text></n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.rank_change>0?'error':'success'">
|
|
||||||
{{item.rank_change}}
|
|
||||||
<n-icon v-if="item.rank_change>0" :component="ArrowUp"/>
|
|
||||||
<n-text v-else-if="item.rank_change==0" ></n-text>
|
|
||||||
<n-icon v-else :component="ArrowDown"/>
|
|
||||||
</n-text>
|
|
||||||
</n-td>
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,73 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {onBeforeMount, onUnmounted, ref} from 'vue'
|
|
||||||
import {HotTopic} from "../../wailsjs/go/main/App";
|
|
||||||
const list = ref([])
|
|
||||||
const task =ref()
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
list.value = await HotTopic(10)
|
|
||||||
setInterval(async ()=>{
|
|
||||||
list.value = await HotTopic(10)
|
|
||||||
}, 1000*10)
|
|
||||||
})
|
|
||||||
onUnmounted(()=>{
|
|
||||||
clearInterval(task.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
function openCenteredWindow(url, width, height) {
|
|
||||||
const left = (window.screen.width - width) / 2;
|
|
||||||
const top = (window.screen.height - height) / 2;
|
|
||||||
|
|
||||||
return window.open(
|
|
||||||
url,
|
|
||||||
'centeredWindow',
|
|
||||||
`width=${width},height=${height},left=${left},top=${top}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function showPage(htid) {
|
|
||||||
openCenteredWindow(`https://gubatopic.eastmoney.com/topic_v3.html?htid=${htid}`, 1000, 600)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-list bordered hoverable clickable>
|
|
||||||
<!-- <template #header>-->
|
|
||||||
<!-- 股吧热门-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<n-list-item v-for="(item, index) in list" :key="index">
|
|
||||||
<n-thing :title="item.nickname" :description="item.desc" :description-style="'font-size: 14px;'" @click="showPage(item.htid)">
|
|
||||||
<template v-if="item.squareImg" #avatar>
|
|
||||||
<n-avatar :src="item.squareImg" :size="60">
|
|
||||||
</n-avatar>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.stock_list" #footer>
|
|
||||||
<n-flex>
|
|
||||||
<n-tag type="info" v-for="(v, i) in item.stock_list" :bordered="false" size="small">
|
|
||||||
{{v.name}}
|
|
||||||
</n-tag>
|
|
||||||
</n-flex>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.clickNumber" #header-extra>
|
|
||||||
<n-flex>
|
|
||||||
<n-button secondary type="warning" size="tiny">讨论数:<n-number-animation
|
|
||||||
show-separator
|
|
||||||
:from="0"
|
|
||||||
:to="item.postNumber"
|
|
||||||
/>
|
|
||||||
</n-button >
|
|
||||||
<n-tag :bordered="false" type="warning" size="small">浏览量:<n-number-animation
|
|
||||||
show-separator
|
|
||||||
:from="0"
|
|
||||||
:to="item.clickNumber"
|
|
||||||
/>
|
|
||||||
</n-tag>
|
|
||||||
</n-flex>
|
|
||||||
</template>
|
|
||||||
</n-thing>
|
|
||||||
</n-list-item>
|
|
||||||
</n-list>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,115 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import {onBeforeMount, ref} from 'vue'
|
|
||||||
import {GetStockList, IndustryResearchReport,EMDictCode} from "../../wailsjs/go/main/App";
|
|
||||||
import {ArrowDownOutline, CaretDown, CaretUp, PulseOutline, Refresh, RefreshCircleSharp,} from "@vicons/ionicons5";
|
|
||||||
|
|
||||||
import {useMessage} from "naive-ui";
|
|
||||||
import {BrowserOpenURL} from "../../wailsjs/runtime";
|
|
||||||
|
|
||||||
const message=useMessage()
|
|
||||||
const list = ref([])
|
|
||||||
|
|
||||||
const options = ref([])
|
|
||||||
|
|
||||||
function getIndustryResearchReport(value) {
|
|
||||||
message.loading("正在刷新数据...")
|
|
||||||
IndustryResearchReport(value).then(result => {
|
|
||||||
console.log(result)
|
|
||||||
list.value = result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(()=>{
|
|
||||||
getIndustryResearchReport('');
|
|
||||||
})
|
|
||||||
|
|
||||||
function ratingChangeName(ratingChange){
|
|
||||||
if(ratingChange===0){
|
|
||||||
return '调高'
|
|
||||||
}else if(ratingChange===1){
|
|
||||||
return '调低'
|
|
||||||
}else if(ratingChange===2){
|
|
||||||
return '首次'
|
|
||||||
}else if(ratingChange===3){
|
|
||||||
return '维持'
|
|
||||||
}else if (ratingChange===4){
|
|
||||||
return '无变化'
|
|
||||||
}else{
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function openWin(code) {
|
|
||||||
BrowserOpenURL("https://pdf.dfcfw.com/pdf/H3_"+code+"_1.pdf?1749744888000.pdf")
|
|
||||||
}
|
|
||||||
|
|
||||||
function EMDictCodeList(keyVal){
|
|
||||||
if (keyVal){
|
|
||||||
EMDictCode('016').then(result => {
|
|
||||||
console.log(result)
|
|
||||||
options.value=result.filter((value,index,array) => value.bkName.includes(keyVal)||value.firstLetter.includes(keyVal)||value.bkCode.includes(keyVal)).map(item => {
|
|
||||||
return {
|
|
||||||
label: item.bkName+" - "+item.bkCode,
|
|
||||||
value: item.bkCode
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
getIndustryResearchReport('')
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
function handleSearch(value) {
|
|
||||||
getIndustryResearchReport(value)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-card>
|
|
||||||
<n-auto-complete :options="options" placeholder="请输入行业名称关键词搜索" clearable filterable :on-select="handleSearch" :on-update:value="EMDictCodeList" />
|
|
||||||
</n-card>
|
|
||||||
<n-table striped size="small">
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<!-- <n-th>代码</n-th>-->
|
|
||||||
<!-- <n-th>名称</n-th>-->
|
|
||||||
<n-th>行业</n-th>
|
|
||||||
<n-th>标题</n-th>
|
|
||||||
<n-th>东财评级</n-th>
|
|
||||||
<n-th>评级变动</n-th>
|
|
||||||
<n-th>机构评级</n-th>
|
|
||||||
<n-th>分析师</n-th>
|
|
||||||
<n-th>机构</n-th>
|
|
||||||
<n-th> <n-flex justify="space-between">日期<n-icon @click="getIndustryResearchReport" color="#409EFF" :size="20" :component="RefreshCircleSharp"/></n-flex></n-th>
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="item in list" :key="item.infoCode">
|
|
||||||
<!-- <n-td>{{item.stockCode}}</n-td>-->
|
|
||||||
<!-- <n-td :title="item.stockCode">-->
|
|
||||||
<!-- <n-popover trigger="hover" placement="right">-->
|
|
||||||
<!-- <template #trigger>-->
|
|
||||||
<!-- <n-tag type="info" :bordered="false">{{item.stockName}}</n-tag>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- <k-line-chart style="width: 800px" :code="getmMarketCode(item.market,item.stockCode)" :chart-height="500" :name="item.stockName" :k-days="20" :dark-theme="true"></k-line-chart>-->
|
|
||||||
<!-- </n-popover>-->
|
|
||||||
<!-- </n-td>-->
|
|
||||||
<n-td><n-tag type="info" :bordered="false">{{item.industryName}}</n-tag></n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-a type="info" @click="openWin(item.infoCode)"><n-text type="success">{{item.title}}</n-text></n-a>
|
|
||||||
</n-td>
|
|
||||||
<n-td><n-text :type="item.emRatingName==='增持'?'error':'info'">
|
|
||||||
{{item.emRatingName}}
|
|
||||||
</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.ratingChange===0?'error':'info'">{{ratingChangeName(item.ratingChange)}}</n-text></n-td>
|
|
||||||
<n-td>{{item.sRatingName }}</n-td>
|
|
||||||
<n-td><n-ellipsis style="max-width: 120px">{{item.researcher}}</n-ellipsis></n-td>
|
|
||||||
<n-td>{{item.orgSName}}</n-td>
|
|
||||||
<n-td>{{item.publishDate.substring(0,10)}}</n-td>
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,108 +0,0 @@
|
|||||||
<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>
|
|
@ -60,7 +60,7 @@ function handleKLine(code,name){
|
|||||||
////console.log("values",values)
|
////console.log("values",values)
|
||||||
let option = {
|
let option = {
|
||||||
title: {
|
title: {
|
||||||
text: name+" "+code,
|
text: name,
|
||||||
left: '20px',
|
left: '20px',
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: darkTheme?'#ccc':'#456'
|
color: darkTheme?'#ccc':'#456'
|
||||||
@ -356,7 +356,7 @@ function handleKLine(code,name){
|
|||||||
chart.setOption(option);
|
chart.setOption(option);
|
||||||
|
|
||||||
chart.on('click',{seriesName:'日K'}, function(params) {
|
chart.on('click',{seriesName:'日K'}, function(params) {
|
||||||
//console.log("click:",params);
|
console.log("click:",params);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,229 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {onBeforeMount, ref} from 'vue'
|
|
||||||
import {LongTigerRank} from "../../wailsjs/go/main/App";
|
|
||||||
import {BrowserOpenURL} from "../../wailsjs/runtime";
|
|
||||||
import {ArrowDownOutline} from "@vicons/ionicons5";
|
|
||||||
import _ from "lodash";
|
|
||||||
import KLineChart from "./KLineChart.vue";
|
|
||||||
import MoneyTrend from "./moneyTrend.vue";
|
|
||||||
import {NButton, NText, useMessage} from "naive-ui";
|
|
||||||
const message = useMessage()
|
|
||||||
|
|
||||||
const lhbList= ref([])
|
|
||||||
const EXPLANATIONs = ref([])
|
|
||||||
|
|
||||||
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 SearchForm= ref({
|
|
||||||
dateValue: formattedDate,
|
|
||||||
EXPLANATION:null,
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
longTiger(formattedDate);
|
|
||||||
})
|
|
||||||
function longTiger_old(date) {
|
|
||||||
if(date) {
|
|
||||||
SearchForm.value.dateValue = date
|
|
||||||
}
|
|
||||||
let loading1=message.loading("正在获取龙虎榜数据...",{
|
|
||||||
duration: 0,
|
|
||||||
})
|
|
||||||
LongTigerRank(date).then(res => {
|
|
||||||
lhbList.value = res
|
|
||||||
loading1.destroy()
|
|
||||||
if (res.length === 0) {
|
|
||||||
message.info("暂无数据,请切换日期")
|
|
||||||
}
|
|
||||||
EXPLANATIONs.value=_.uniqBy(_.map(lhbList.value,function (item){
|
|
||||||
return {
|
|
||||||
label: item['EXPLANATION'],
|
|
||||||
value: item['EXPLANATION'],
|
|
||||||
}
|
|
||||||
}),'label');
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function longTiger(date) {
|
|
||||||
if (date) {
|
|
||||||
SearchForm.value.dateValue = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
let loading1 = message.loading("正在获取龙虎榜数据...", {
|
|
||||||
duration: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetchDate = (currentDate, retryCount = 0) => {
|
|
||||||
if (retryCount > 7) { // 防止无限循环,最多尝试7次
|
|
||||||
lhbList.value = [];
|
|
||||||
EXPLANATIONs.value = [];
|
|
||||||
loading1.destroy();
|
|
||||||
message.info("暂无历史数据");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LongTigerRank(currentDate).then(res => {
|
|
||||||
if (res.length === 0) {
|
|
||||||
const previousDate = new Date(currentDate);
|
|
||||||
previousDate.setDate(previousDate.getDate() - 1);
|
|
||||||
|
|
||||||
const year = previousDate.getFullYear();
|
|
||||||
const month = String(previousDate.getMonth() + 1).padStart(2, '0');
|
|
||||||
const day = String(previousDate.getDate()).padStart(2, '0');
|
|
||||||
const prevFormattedDate = `${year}-${month}-${day}`;
|
|
||||||
|
|
||||||
message.info(`当前日期 ${currentDate} 暂无数据,尝试查询前一日:${prevFormattedDate}`);
|
|
||||||
|
|
||||||
SearchForm.value.dateValue = prevFormattedDate;
|
|
||||||
fetchDate(prevFormattedDate, retryCount + 1); // 递归调用
|
|
||||||
} else {
|
|
||||||
lhbList.value = res;
|
|
||||||
loading1.destroy();
|
|
||||||
EXPLANATIONs.value = _.uniqBy(_.map(lhbList.value, function (item) {
|
|
||||||
return {
|
|
||||||
label: item['EXPLANATION'],
|
|
||||||
value: item['EXPLANATION'],
|
|
||||||
};
|
|
||||||
}), 'label');
|
|
||||||
}
|
|
||||||
}).catch(err => {
|
|
||||||
loading1.destroy();
|
|
||||||
message.error("获取数据失败,请重试");
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchDate(date || formattedDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEXPLANATION(value, option){
|
|
||||||
SearchForm.value.EXPLANATION = value
|
|
||||||
if(value){
|
|
||||||
LongTigerRank(SearchForm.value.dateValue).then(res => {
|
|
||||||
lhbList.value=_.filter(res, function(o) { return o['EXPLANATION']===value; });
|
|
||||||
if (res.length === 0) {
|
|
||||||
message.info("暂无数据,请切换日期")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
longTiger(SearchForm.value.dateValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-form :model="SearchForm" >
|
|
||||||
<n-grid :cols="24" :x-gap="24">
|
|
||||||
<n-form-item-gi :span="4" label="日期" path="dateValue" label-placement="left">
|
|
||||||
<n-date-picker v-model:formatted-value="SearchForm.dateValue"
|
|
||||||
value-format="yyyy-MM-dd" type="date" :on-update:value="(v,v2)=>longTiger(v2)"/>
|
|
||||||
|
|
||||||
</n-form-item-gi>
|
|
||||||
<n-form-item-gi :span="8" label="上榜原因" path="EXPLANATION" label-placement="left">
|
|
||||||
<n-select clearable placeholder="上榜原因过滤" v-model:value="SearchForm.EXPLANATION" :options="EXPLANATIONs" :on-update:value="handleEXPLANATION"/>
|
|
||||||
</n-form-item-gi>
|
|
||||||
<n-form-item-gi :span="10" label="" label-placement="left">
|
|
||||||
<n-text type="error">*当天的龙虎榜数据通常在收盘结束后一小时左右更新</n-text>
|
|
||||||
</n-form-item-gi>
|
|
||||||
</n-grid>
|
|
||||||
</n-form>
|
|
||||||
<n-table :single-line="false" striped>
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<n-th>代码</n-th>
|
|
||||||
<!-- <n-th width="90px">日期</n-th>-->
|
|
||||||
<n-th width="60px">名称</n-th>
|
|
||||||
<n-th>收盘价</n-th>
|
|
||||||
<n-th width="60px">涨跌幅</n-th>
|
|
||||||
<n-th>龙虎榜净买额(万)</n-th>
|
|
||||||
<n-th>龙虎榜买入额(万)</n-th>
|
|
||||||
<n-th>龙虎榜卖出额(万)</n-th>
|
|
||||||
<n-th>龙虎榜成交额(万)</n-th>
|
|
||||||
<!-- <n-th>市场总成交额(万)</n-th>-->
|
|
||||||
<!-- <n-th>净买额占总成交比</n-th>-->
|
|
||||||
<!-- <n-th>成交额占总成交比</n-th>-->
|
|
||||||
<n-th width="60px" data-field="TURNOVERRATE">换手率<n-icon :component="ArrowDownOutline" /></n-th>
|
|
||||||
<n-th>流通市值(亿)</n-th>
|
|
||||||
<n-th>上榜原因</n-th>
|
|
||||||
<!-- <n-th>解读</n-th>-->
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="(item, index) in lhbList" :key="index">
|
|
||||||
<n-td>
|
|
||||||
<n-tag :bordered=false type="info">{{ item.SECUCODE.split('.')[1].toLowerCase()+item.SECUCODE.split('.')[0] }}</n-tag>
|
|
||||||
</n-td>
|
|
||||||
<!-- <n-td>
|
|
||||||
{{item.TRADE_DATE.substring(0,10)}}
|
|
||||||
</n-td>-->
|
|
||||||
<n-td>
|
|
||||||
<!-- <n-text :type="item.CHANGE_RATE>0?'error':'success'">{{ item.SECURITY_NAME_ABBR }}</n-text>-->
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-button tag="a" text :type="item.CHANGE_RATE>0?'error':'success'" :bordered=false >{{ item.SECURITY_NAME_ABBR }}</n-button>
|
|
||||||
</template>
|
|
||||||
<k-line-chart style="width: 800px" :code="item.SECUCODE.split('.')[1].toLowerCase()+item.SECUCODE.split('.')[0]" :chart-height="500" :name="item.SECURITY_NAME_ABBR" :k-days="20" :dark-theme="true"></k-line-chart>
|
|
||||||
</n-popover>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.CHANGE_RATE>0?'error':'success'">{{ item.CLOSE_PRICE }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.CHANGE_RATE>0?'error':'success'">{{ (item.CHANGE_RATE).toFixed(2) }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<!-- <n-text :type="item.BILLBOARD_NET_AMT>0?'error':'success'">{{ (item.BILLBOARD_NET_AMT/10000).toFixed(2) }}</n-text>-->
|
|
||||||
|
|
||||||
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-button tag="a" text :type="item.BILLBOARD_NET_AMT>0?'error':'success'" :bordered=false >{{ (item.BILLBOARD_NET_AMT/10000).toFixed(2) }}</n-button>
|
|
||||||
</template>
|
|
||||||
<money-trend :code="item.SECUCODE.split('.')[1].toLowerCase()+item.SECUCODE.split('.')[0]" :name="item.SECURITY_NAME_ABBR" :days="360" :dark-theme="true" :chart-height="500" style="width: 800px"></money-trend>
|
|
||||||
</n-popover>
|
|
||||||
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="'error'">{{ (item.BILLBOARD_BUY_AMT/10000).toFixed(2) }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="'success'">{{ (item.BILLBOARD_SELL_AMT/10000).toFixed(2) }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="'info'">{{ (item.BILLBOARD_DEAL_AMT/10000).toFixed(2) }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<!-- <n-td>-->
|
|
||||||
<!-- <n-text :type="'info'">{{ (item.ACCUM_AMOUNT/10000).toFixed(2) }}</n-text>-->
|
|
||||||
<!-- </n-td>-->
|
|
||||||
<!-- <n-td>-->
|
|
||||||
<!-- <n-text :type="item.DEAL_NET_RATIO>0?'error':'success'">{{ (item.DEAL_NET_RATIO).toFixed(2) }}%</n-text>-->
|
|
||||||
<!-- </n-td>-->
|
|
||||||
<!-- <n-td>-->
|
|
||||||
<!-- <n-text :type="'info'">{{ (item.DEAL_AMOUNT_RATIO).toFixed(2) }}%</n-text>-->
|
|
||||||
<!-- </n-td>-->
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="'info'">{{ (item.TURNOVERRATE).toFixed(2) }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="'info'">{{ (item.FREE_MARKET_CAP/100000000).toFixed(2) }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="'info'">{{ item.EXPLANATION }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<!-- <n-td>
|
|
||||||
<n-text :type="item.CHANGE_RATE>0?'error':'success'">{{ item.EXPLAIN }}</n-text>
|
|
||||||
</n-td>-->
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,126 +0,0 @@
|
|||||||
<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>
|
|
@ -1,148 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {onBeforeMount, ref} from 'vue'
|
|
||||||
import {GetStockList, StockNotice} from "../../wailsjs/go/main/App";
|
|
||||||
import {BrowserOpenURL} from "../../wailsjs/runtime";
|
|
||||||
import {RefreshCircleSharp} from "@vicons/ionicons5";
|
|
||||||
import _ from "lodash";
|
|
||||||
import KLineChart from "./KLineChart.vue";
|
|
||||||
import MoneyTrend from "./moneyTrend.vue";
|
|
||||||
import {useMessage} from "naive-ui";
|
|
||||||
|
|
||||||
const {stockCode}=defineProps(
|
|
||||||
{
|
|
||||||
stockCode: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const list = ref([])
|
|
||||||
const options = ref([])
|
|
||||||
const message=useMessage()
|
|
||||||
function getNotice(stockCodes) {
|
|
||||||
StockNotice(stockCodes).then(result => {
|
|
||||||
console.log(result)
|
|
||||||
list.value = result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount (()=>{
|
|
||||||
//message.info("正在获取数据"+stockCode)
|
|
||||||
getNotice(stockCode);
|
|
||||||
})
|
|
||||||
|
|
||||||
function findStockList(query){
|
|
||||||
if (query){
|
|
||||||
GetStockList(query).then(result => {
|
|
||||||
options.value=result.map(item => {
|
|
||||||
return {
|
|
||||||
label: item.name+" - "+item.ts_code,
|
|
||||||
value: item.ts_code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
getNotice("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function handleSearch(value) {
|
|
||||||
getNotice(value)
|
|
||||||
}
|
|
||||||
function openWin(code) {
|
|
||||||
BrowserOpenURL("https://pdf.dfcfw.com/pdf/H2_"+code+"_1.pdf?1750092081000.pdf")
|
|
||||||
}
|
|
||||||
function getTypeColor(name){
|
|
||||||
if(name.includes("质押")||name.includes("冻结")||name.includes("解冻")||name.includes("解押")||name.includes("解禁")){
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
if(name.includes("异常")||name.includes("减持")||name.includes("增发")||name.includes("重大")){
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
if(name.includes("季度报告")||name.includes("年度报告")||name.includes("澄清公告")||name.includes("风险")){
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
if(name.includes("终止")||name.includes("复牌")||name.includes("停牌")||name.includes("退市")){
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
if(name.includes("破产")||name.includes("清算")){
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
if(name.includes("回购")||name.includes("重组")||name.includes("诉讼")||name.includes("仲裁")||name.includes("转让")||name.includes("收购")){
|
|
||||||
return "warning"
|
|
||||||
}
|
|
||||||
if(name.includes("调研")||name.includes("募集")){
|
|
||||||
return "warning"
|
|
||||||
}
|
|
||||||
|
|
||||||
return "info"
|
|
||||||
|
|
||||||
}
|
|
||||||
function getmMarketCode(market,code) {
|
|
||||||
if(market==="0"){
|
|
||||||
return "sz"+code
|
|
||||||
}else if(market==="1"){
|
|
||||||
return "sh"+code
|
|
||||||
}else if(market==="2"){
|
|
||||||
return "bj"+code
|
|
||||||
}else if(market==="3"){
|
|
||||||
return "hk"+code
|
|
||||||
}else{
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-card>
|
|
||||||
<n-auto-complete :options="options" placeholder="请输入A股名称或者代码" clearable filterable :on-select="handleSearch" :on-update:value="findStockList" />
|
|
||||||
</n-card>
|
|
||||||
<n-table striped size="small">
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<n-th>股票代码</n-th>
|
|
||||||
<n-th>股票名称</n-th>
|
|
||||||
<n-th>公告标题</n-th>
|
|
||||||
<n-th>公告类型</n-th>
|
|
||||||
<n-th>公告日期</n-th>
|
|
||||||
<n-th><n-flex>数据更新时间<n-icon @click="getNotice('')" color="#409EFF" :size="20" :component="RefreshCircleSharp"/></n-flex></n-th>
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="item in list" :key="item.art_code">
|
|
||||||
<n-td>
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-tag type="info" :bordered="false">{{item.codes[0].stock_code }}</n-tag>
|
|
||||||
</template>
|
|
||||||
<money-trend style="width: 800px" :code="getmMarketCode(item.codes[0].market_code,item.codes[0].stock_code)" :name="item.codes[0].short_name" :days="360" :dark-theme="true" :chart-height="500"></money-trend>
|
|
||||||
</n-popover>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-tag type="info" :bordered="false">{{item.codes[0].short_name }}</n-tag>
|
|
||||||
</template>
|
|
||||||
<k-line-chart style="width: 800px" :code="getmMarketCode(item.codes[0].market_code,item.codes[0].stock_code)" :chart-height="500" :name="item.codes[0].short_name" :k-days="20" :dark-theme="true"></k-line-chart>
|
|
||||||
</n-popover>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-a type="info" @click="openWin(item.art_code)"><n-text :type="getTypeColor(item.columns[0].column_name)"> {{item.title}}</n-text></n-a>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="getTypeColor(item.columns[0].column_name)">{{item.columns[0].column_name }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-tag type="info">{{item.notice_date.substring(0,10) }}</n-tag>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-tag type="info">{{item.display_time.substring(0,19)}}</n-tag>
|
|
||||||
</n-td>
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,136 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import {onBeforeMount, ref} from 'vue'
|
|
||||||
import {GetStockList, StockResearchReport} from "../../wailsjs/go/main/App";
|
|
||||||
import {ArrowDownOutline, CaretDown, CaretUp, PulseOutline, Refresh, RefreshCircleSharp,} from "@vicons/ionicons5";
|
|
||||||
|
|
||||||
import KLineChart from "./KLineChart.vue";
|
|
||||||
import MoneyTrend from "./moneyTrend.vue";
|
|
||||||
import {useMessage} from "naive-ui";
|
|
||||||
import {BrowserOpenURL} from "../../wailsjs/runtime";
|
|
||||||
|
|
||||||
const {stockCode}=defineProps(
|
|
||||||
{
|
|
||||||
stockCode: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const message=useMessage()
|
|
||||||
const list = ref([])
|
|
||||||
|
|
||||||
const options = ref([])
|
|
||||||
|
|
||||||
function getStockResearchReport(value) {
|
|
||||||
StockResearchReport(value).then(result => {
|
|
||||||
//console.log(result)
|
|
||||||
list.value = result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(()=>{
|
|
||||||
getStockResearchReport(stockCode);
|
|
||||||
})
|
|
||||||
|
|
||||||
function ratingChangeName(ratingChange){
|
|
||||||
if(ratingChange===0){
|
|
||||||
return '调高'
|
|
||||||
}else if(ratingChange===1){
|
|
||||||
return '调低'
|
|
||||||
}else if(ratingChange===2){
|
|
||||||
return '首次'
|
|
||||||
}else if(ratingChange===3){
|
|
||||||
return '维持'
|
|
||||||
}else if (ratingChange===4){
|
|
||||||
return '无变化'
|
|
||||||
}else{
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getmMarketCode(market,code) {
|
|
||||||
if(market==="SHENZHEN"){
|
|
||||||
return "sz"+code
|
|
||||||
}else if(market==="SHANGHAI"){
|
|
||||||
return "sh"+code
|
|
||||||
}else if(market==="BEIJING"){
|
|
||||||
return "bj"+code
|
|
||||||
}else if(market==="HONGKONG"){
|
|
||||||
return "hk"+code
|
|
||||||
}else{
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function openWin(code) {
|
|
||||||
BrowserOpenURL("https://pdf.dfcfw.com/pdf/H3_"+code+"_1.pdf?1749744888000.pdf")
|
|
||||||
}
|
|
||||||
|
|
||||||
function findStockList(query){
|
|
||||||
if (query){
|
|
||||||
GetStockList(query).then(result => {
|
|
||||||
options.value=result.map(item => {
|
|
||||||
return {
|
|
||||||
label: item.name+" - "+item.ts_code,
|
|
||||||
value: item.ts_code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
getStockResearchReport('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function handleSearch(value) {
|
|
||||||
getStockResearchReport(value)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-card>
|
|
||||||
<n-auto-complete :options="options" placeholder="请输入A股名称或者代码" clearable filterable :on-select="handleSearch" :on-update:value="findStockList" />
|
|
||||||
</n-card>
|
|
||||||
<n-table striped size="small">
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<!-- <n-th>代码</n-th>-->
|
|
||||||
<n-th>名称</n-th>
|
|
||||||
<n-th>行业</n-th>
|
|
||||||
<n-th>标题</n-th>
|
|
||||||
<n-th>东财评级</n-th>
|
|
||||||
<n-th>评级变动</n-th>
|
|
||||||
<n-th>机构评级</n-th>
|
|
||||||
<n-th>分析师</n-th>
|
|
||||||
<n-th>机构</n-th>
|
|
||||||
<n-th> <n-flex justify="space-between">日期<n-icon @click="getStockResearchReport" color="#409EFF" :size="20" :component="RefreshCircleSharp"/></n-flex></n-th>
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="item in list" :key="item.infoCode">
|
|
||||||
<!-- <n-td>{{item.stockCode}}</n-td>-->
|
|
||||||
<n-td :title="item.stockCode">
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-tag type="info" :bordered="false">{{item.stockName}}</n-tag>
|
|
||||||
</template>
|
|
||||||
<k-line-chart style="width: 800px" :code="getmMarketCode(item.market,item.stockCode)" :chart-height="500" :name="item.stockName" :k-days="20" :dark-theme="true"></k-line-chart>
|
|
||||||
</n-popover>
|
|
||||||
</n-td>
|
|
||||||
<n-td><n-tag type="info" :bordered="false">{{item.indvInduName}}</n-tag></n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-a type="info" @click="openWin(item.infoCode)">{{item.title}}</n-a>
|
|
||||||
</n-td>
|
|
||||||
<n-td><n-text :type="item.emRatingName==='增持'?'error':'info'">
|
|
||||||
{{item.emRatingName}}
|
|
||||||
</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.ratingChange===0?'error':'info'">{{ratingChangeName(item.ratingChange)}}</n-text></n-td>
|
|
||||||
<n-td>{{item.sRatingName}}</n-td>
|
|
||||||
<n-td>{{item.researcher}}</n-td>
|
|
||||||
<n-td>{{item.orgSName}}</n-td>
|
|
||||||
<n-td>{{item.publishDate.substring(0,10)}}</n-td>
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -44,8 +44,8 @@ EventsOn("updateVersion",async (msg) => {
|
|||||||
|
|
||||||
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
|
||||||
//console.log("GitHub UTC 时间:", utcDate);
|
console.log("GitHub UTC 时间:", utcDate);
|
||||||
//console.log("转换后的本地时间:", formattedDate);
|
console.log("转换后的本地时间:", formattedDate);
|
||||||
notify.info({
|
notify.info({
|
||||||
avatar: () =>
|
avatar: () =>
|
||||||
h(NAvatar, {
|
h(NAvatar, {
|
||||||
@ -135,7 +135,6 @@ EventsOn("updateVersion",async (msg) => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
感谢以下开发者:
|
感谢以下开发者:
|
||||||
<a href="https://github.com/CodeNoobLH" target="_blank">浓睡不消残酒</a><n-divider vertical />
|
|
||||||
<a href="https://github.com/gnim2600" target="_blank">@gnim2600</a><n-divider vertical />
|
<a href="https://github.com/gnim2600" target="_blank">@gnim2600</a><n-divider vertical />
|
||||||
<a href="https://github.com/XXXiaohuayanGGG" target="_blank">@XXXiaohuayanGGG</a><n-divider vertical />
|
<a href="https://github.com/XXXiaohuayanGGG" target="_blank">@XXXiaohuayanGGG</a><n-divider vertical />
|
||||||
<a href="https://github.com/2lovecode" target="_blank">@2lovecode</a><n-divider vertical />
|
<a href="https://github.com/2lovecode" target="_blank">@2lovecode</a><n-divider vertical />
|
||||||
|
@ -47,7 +47,7 @@ onBeforeMount(()=>{
|
|||||||
})
|
})
|
||||||
GetFollowedFund().then(result => {
|
GetFollowedFund().then(result => {
|
||||||
followList.value = result
|
followList.value = result
|
||||||
//console.log("followList",followList.value)
|
console.log("followList",followList.value)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ onMounted(() => {
|
|||||||
//ws.value = new WebSocket('ws://localhost:16688/ws'); // 替换为你的 WebSocket 服务器地址
|
//ws.value = new WebSocket('ws://localhost:16688/ws'); // 替换为你的 WebSocket 服务器地址
|
||||||
|
|
||||||
ws.value.onopen = () => {
|
ws.value.onopen = () => {
|
||||||
//console.log('WebSocket 连接已打开');
|
console.log('WebSocket 连接已打开');
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.value.onmessage = (event) => {
|
ws.value.onmessage = (event) => {
|
||||||
@ -74,13 +74,13 @@ onMounted(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ws.value.onclose = () => {
|
ws.value.onclose = () => {
|
||||||
//console.log('WebSocket 连接已关闭');
|
console.log('WebSocket 连接已关闭');
|
||||||
};
|
};
|
||||||
|
|
||||||
ticker.value=setInterval(() => {
|
ticker.value=setInterval(() => {
|
||||||
GetFollowedFund().then(result => {
|
GetFollowedFund().then(result => {
|
||||||
followList.value = result
|
followList.value = result
|
||||||
//console.log("followList",followList.value)
|
console.log("followList",followList.value)
|
||||||
})
|
})
|
||||||
}, 1000*60)
|
}, 1000*60)
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ function AddFund(){
|
|||||||
message.success("关注成功")
|
message.success("关注成功")
|
||||||
GetFollowedFund().then(result => {
|
GetFollowedFund().then(result => {
|
||||||
followList.value = result
|
followList.value = result
|
||||||
//console.log("followList",followList.value)
|
console.log("followList",followList.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -114,7 +114,7 @@ function unFollow(code){
|
|||||||
message.success("取消关注成功")
|
message.success("取消关注成功")
|
||||||
GetFollowedFund().then(result => {
|
GetFollowedFund().then(result => {
|
||||||
followList.value = result
|
followList.value = result
|
||||||
//console.log("followList",followList.value)
|
console.log("followList",followList.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
|
|
||||||
import {CaretDown, CaretUp, RefreshCircleOutline} from "@vicons/ionicons5";
|
|
||||||
import {NText,useMessage} from "naive-ui";
|
|
||||||
import {onBeforeUnmount, onMounted, onUnmounted, ref} from "vue";
|
|
||||||
import {GetIndustryMoneyRankSina} from "../../wailsjs/go/main/App";
|
|
||||||
import KLineChart from "./KLineChart.vue";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
headerTitle: {
|
|
||||||
type: String,
|
|
||||||
default: '行业资金排名(净流入)'
|
|
||||||
},
|
|
||||||
fenlei: {
|
|
||||||
type: String,
|
|
||||||
default: '0'
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
type: String,
|
|
||||||
default: 'netamount'
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const message = useMessage()
|
|
||||||
const dataList= ref([])
|
|
||||||
const sort = ref(props.sort)
|
|
||||||
const fenlei= ref(props.fenlei)
|
|
||||||
|
|
||||||
const interval = ref(null)
|
|
||||||
onMounted(()=>{
|
|
||||||
sort.value=props.sort
|
|
||||||
fenlei.value=props.fenlei
|
|
||||||
GetRankData()
|
|
||||||
interval.value=setInterval(()=>{
|
|
||||||
GetRankData()
|
|
||||||
},1000*60)
|
|
||||||
})
|
|
||||||
onBeforeUnmount(()=>{
|
|
||||||
clearInterval(interval.value)
|
|
||||||
})
|
|
||||||
function GetRankData(){
|
|
||||||
message.loading("正在刷新数据...")
|
|
||||||
GetIndustryMoneyRankSina(fenlei.value,sort.value).then(result => {
|
|
||||||
if(result.length>0){
|
|
||||||
dataList.value = result
|
|
||||||
//console.log(result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-table striped size="small">
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<n-th>板块名称</n-th>
|
|
||||||
<n-th>涨跌幅</n-th>
|
|
||||||
<n-th>流入资金/万</n-th>
|
|
||||||
<n-th>流出资金/万</n-th>
|
|
||||||
<n-th>净流入/万<n-icon v-if="sort==='0'" :component="CaretDown"/><n-icon v-if="sort==='1'" :component="CaretUp"/></n-th>
|
|
||||||
<n-th>净流入率</n-th>
|
|
||||||
<n-th>领涨股</n-th>
|
|
||||||
<n-th>涨跌幅</n-th>
|
|
||||||
<n-th>最新价</n-th>
|
|
||||||
<n-th>净流入率</n-th>
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="item in dataList" :key="item.category">
|
|
||||||
<n-td><n-tag :bordered=false type="info">{{item.name}}</n-tag></n-td>
|
|
||||||
<n-td> <n-text :type="item.avg_changeratio>0?'error':'success'">{{(item.avg_changeratio*100).toFixed(2)}}%</n-text></n-td>
|
|
||||||
<n-td><n-text type="info">{{(item.inamount/10000).toFixed(2)}}</n-text></n-td>
|
|
||||||
<n-td><n-text type="info">{{(item.outamount/10000).toFixed(2)}}</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.netamount>0?'error':'success'">{{(item.netamount/10000).toFixed(2)}}</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.ratioamount>0?'error':'success'">{{(item.ratioamount*100).toFixed(2)}}%</n-text></n-td>
|
|
||||||
<n-td>
|
|
||||||
<!-- <n-text type="info">{{item.ts_name}}</n-text>-->
|
|
||||||
<n-popover trigger="hover" placement="right">
|
|
||||||
<template #trigger>
|
|
||||||
<n-button tag="a" text :type="item.ts_changeratio>0?'error':'success'" :bordered=false >{{ item.ts_name }}</n-button>
|
|
||||||
</template>
|
|
||||||
<k-line-chart style="width: 800px" :code="item.ts_symbol" :chart-height="500" :name="item.ts_name" :k-days="20" :dark-theme="true"></k-line-chart>
|
|
||||||
</n-popover>
|
|
||||||
</n-td>
|
|
||||||
<n-td><n-text :type="item.ts_changeratio>0?'error':'success'">{{(item.ts_changeratio*100).toFixed(2)}}%</n-text></n-td>
|
|
||||||
<n-td><n-text type="info">{{item.ts_trade}}</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.ts_ratioamount>0?'error':'success'">{{(item.ts_ratioamount*100).toFixed(2)}}%</n-text></n-td>
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -2,37 +2,21 @@
|
|||||||
import {computed, h, onBeforeMount, onBeforeUnmount, ref} from 'vue'
|
import {computed, h, onBeforeMount, onBeforeUnmount, ref} from 'vue'
|
||||||
import {
|
import {
|
||||||
GetAIResponseResult,
|
GetAIResponseResult,
|
||||||
GetConfig,
|
GetConfig, GetIndustryRank, GetPromptTemplates,
|
||||||
GetIndustryRank,
|
|
||||||
GetPromptTemplates,
|
|
||||||
GetTelegraphList,
|
GetTelegraphList,
|
||||||
GlobalStockIndexes,
|
GlobalStockIndexes, ReFleshTelegraphList,
|
||||||
ReFleshTelegraphList,
|
SaveAIResponseResult, SaveAsMarkdown, ShareAnalysis,
|
||||||
SaveAIResponseResult,
|
|
||||||
SaveAsMarkdown,
|
|
||||||
ShareAnalysis,
|
|
||||||
SummaryStockNews
|
SummaryStockNews
|
||||||
} from "../../wailsjs/go/main/App";
|
} from "../../wailsjs/go/main/App";
|
||||||
import {EventsOff, EventsOn} from "../../wailsjs/runtime";
|
import {EventsOff, EventsOn} from "../../wailsjs/runtime";
|
||||||
import NewsList from "./newsList.vue";
|
import NewsList from "./newsList.vue";
|
||||||
import KLineChart from "./KLineChart.vue";
|
import KLineChart from "./KLineChart.vue";
|
||||||
import { CaretDown, CaretUp, PulseOutline,} from "@vicons/ionicons5";
|
import {Add, CaretDown, CaretUp, ChatboxOutline, PulseOutline,} from "@vicons/ionicons5";
|
||||||
import {NAvatar, NButton, NFlex, NText, useMessage, useNotification} from "naive-ui";
|
import {NAvatar, NButton, NFlex, NText, useMessage, useNotification} from "naive-ui";
|
||||||
import {MdPreview} from "md-editor-v3";
|
import {ExportPDF} from "@vavt/v3-extension";
|
||||||
|
import {MdEditor, MdPreview} from "md-editor-v3";
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import RankTable from "./rankTable.vue";
|
import RankTable from "./rankTable.vue";
|
||||||
import IndustryMoneyRank from "./industryMoneyRank.vue";
|
|
||||||
import StockResearchReportList from "./StockResearchReportList.vue";
|
|
||||||
import StockNoticeList from "./StockNoticeList.vue";
|
|
||||||
import LongTigerRankList from "./LongTigerRankList.vue";
|
|
||||||
import IndustryResearchReportList from "./IndustryResearchReportList.vue";
|
|
||||||
import HotStockList from "./HotStockList.vue";
|
|
||||||
import HotEvents from "./HotEvents.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');
|
||||||
|
|
||||||
@ -42,6 +26,7 @@ const panelHeight = ref(window.innerHeight - 240)
|
|||||||
|
|
||||||
const telegraphList = ref([])
|
const telegraphList = ref([])
|
||||||
const sinaNewsList = ref([])
|
const sinaNewsList = ref([])
|
||||||
|
|
||||||
const common = ref([])
|
const common = ref([])
|
||||||
const america = ref([])
|
const america = ref([])
|
||||||
const europe = ref([])
|
const europe = ref([])
|
||||||
@ -65,12 +50,9 @@ const sysPromptOptions = ref([])
|
|||||||
const userPromptOptions=ref([])
|
const userPromptOptions=ref([])
|
||||||
const promptTemplates=ref([])
|
const promptTemplates=ref([])
|
||||||
const industryRanks=ref([])
|
const industryRanks=ref([])
|
||||||
const sort = ref("0")
|
const sort = ref("")
|
||||||
|
const sortIcon= ref(h(CaretDown))
|
||||||
const nowTab=ref("市场快讯")
|
const nowTab=ref("市场快讯")
|
||||||
const indexInterval = ref(null)
|
|
||||||
const indexIndustryRank = ref(null)
|
|
||||||
const stockCode= ref('')
|
|
||||||
|
|
||||||
function getIndex() {
|
function getIndex() {
|
||||||
GlobalStockIndexes().then((res) => {
|
GlobalStockIndexes().then((res) => {
|
||||||
globalStockIndexes.value = res
|
globalStockIndexes.value = res
|
||||||
@ -82,11 +64,8 @@ function getIndex() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
nowTab.value=route.query.name
|
nowTab.value=route.query.name
|
||||||
stockCode.value = route.query.stockCode
|
|
||||||
GetConfig().then(result => {
|
GetConfig().then(result => {
|
||||||
summaryBTN.value= result.openAiEnable
|
summaryBTN.value= result.openAiEnable
|
||||||
darkTheme.value = result.darkTheme
|
darkTheme.value = result.darkTheme
|
||||||
@ -105,11 +84,11 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
getIndex();
|
getIndex();
|
||||||
industryRank();
|
industryRank();
|
||||||
indexInterval.value = setInterval(() => {
|
setInterval(() => {
|
||||||
getIndex()
|
getIndex()
|
||||||
}, 3000)
|
}, 3000)
|
||||||
|
|
||||||
indexIndustryRank.value = setInterval(() => {
|
setInterval(() => {
|
||||||
industryRank()
|
industryRank()
|
||||||
},1000*10)
|
},1000*10)
|
||||||
})
|
})
|
||||||
@ -119,8 +98,6 @@ onBeforeUnmount(() => {
|
|||||||
EventsOff("newTelegraph")
|
EventsOff("newTelegraph")
|
||||||
EventsOff("newSinaNews")
|
EventsOff("newSinaNews")
|
||||||
EventsOff("summaryStockNews")
|
EventsOff("summaryStockNews")
|
||||||
clearInterval(indexInterval.value)
|
|
||||||
clearInterval(indexIndustryRank.value)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
EventsOn("changeMarketTab" ,async (msg) => {
|
EventsOn("changeMarketTab" ,async (msg) => {
|
||||||
@ -160,21 +137,15 @@ function getAreaName(code) {
|
|||||||
return "其他"
|
return "其他"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function industryRank(){
|
||||||
function changeIndustryRankSort() {
|
|
||||||
if(sort.value==="0"){
|
if(sort.value==="0"){
|
||||||
sort.value="1"
|
sort.value="1"
|
||||||
}else{
|
}else{
|
||||||
sort.value="0"
|
sort.value="0"
|
||||||
}
|
}
|
||||||
industryRank()
|
|
||||||
}
|
|
||||||
|
|
||||||
function industryRank() {
|
|
||||||
|
|
||||||
GetIndustryRank(sort.value,150).then(result => {
|
GetIndustryRank(sort.value,150).then(result => {
|
||||||
if(result.length>0){
|
if(result.length>0){
|
||||||
//console.log(result)
|
console.log(result)
|
||||||
industryRanks.value = result
|
industryRanks.value = result
|
||||||
}else{
|
}else{
|
||||||
message.info("暂无数据")
|
message.info("暂无数据")
|
||||||
@ -188,7 +159,6 @@ function reAiSummary() {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
SummaryStockNews(question.value,sysPromptId.value)
|
SummaryStockNews(question.value,sysPromptId.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAiSummary(){
|
function getAiSummary(){
|
||||||
summaryModal.value = true
|
summaryModal.value = true
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@ -259,13 +229,11 @@ async function copyToClipboard() {
|
|||||||
message.error('复制失败: ' + err);
|
message.error('复制失败: ' + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAsMarkdown(){
|
function saveAsMarkdown(){
|
||||||
SaveAsMarkdown('市场资讯','市场资讯').then(result => {
|
SaveAsMarkdown('市场资讯','市场资讯').then(result => {
|
||||||
message.success(result)
|
message.success(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function share(){
|
function share(){
|
||||||
ShareAnalysis('市场资讯','市场资讯').then(msg => {
|
ShareAnalysis('市场资讯','市场资讯').then(msg => {
|
||||||
//message.info(msg)
|
//message.info(msg)
|
||||||
@ -291,7 +259,7 @@ function share() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ReFlesh(source){
|
function ReFlesh(source){
|
||||||
//console.log("ReFlesh:", source)
|
console.log("ReFlesh:",source)
|
||||||
ReFleshTelegraphList(source).then(res => {
|
ReFleshTelegraphList(source).then(res => {
|
||||||
if(source==="财联社电报"){
|
if(source==="财联社电报"){
|
||||||
telegraphList.value = res
|
telegraphList.value = res
|
||||||
@ -329,16 +297,11 @@ function ReFlesh(source) {
|
|||||||
<n-grid :cols="3" :y-gap="0">
|
<n-grid :cols="3" :y-gap="0">
|
||||||
<n-gi>
|
<n-gi>
|
||||||
|
|
||||||
<n-text :type="item.zdf>0?'error':'success'">
|
<n-text :type="item.zdf>0?'error':'success'"><n-image :src="item.img" width="20"/> {{ item.name }}</n-text>
|
||||||
<n-image :src="item.img" width="20"/> {{ item.name }}
|
|
||||||
</n-text>
|
|
||||||
</n-gi>
|
</n-gi>
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<n-text :type="item.zdf>0?'error':'success'">{{ item.zxj }}</n-text>
|
<n-text :type="item.zdf>0?'error':'success'">{{ item.zxj }}</n-text>
|
||||||
<n-text :type="item.zdf>0?'error':'success'">
|
<n-text :type="item.zdf>0?'error':'success'"><n-number-animation :precision="2" :from="0" :to="item.zdf" />%</n-text>
|
||||||
<n-number-animation :precision="2" :from="0" :to="item.zdf"/>
|
|
||||||
%
|
|
||||||
</n-text>
|
|
||||||
|
|
||||||
</n-gi>
|
</n-gi>
|
||||||
<n-gi>
|
<n-gi>
|
||||||
@ -420,16 +383,11 @@ function ReFlesh(source) {
|
|||||||
</n-tabs>
|
</n-tabs>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="行业排名" tab="行业排名">
|
<n-tab-pane name="行业排名" tab="行业排名">
|
||||||
<n-tabs type="card" animated>
|
|
||||||
<n-tab-pane name="行业涨幅排名" tab="行业涨幅排名">
|
|
||||||
<n-table striped>
|
<n-table striped>
|
||||||
<n-thead>
|
<n-thead>
|
||||||
<n-tr>
|
<n-tr>
|
||||||
<n-th>行业名称</n-th>
|
<n-th>行业名称</n-th>
|
||||||
<n-th @click="changeIndustryRankSort">行业涨幅
|
<n-th @click="industryRank">行业涨幅<n-icon v-if="sort==='0'" :component="CaretDown"/><n-icon v-if="sort==='1'" :component="CaretUp"/></n-th>
|
||||||
<n-icon v-if="sort==='0'" :component="CaretDown"/>
|
|
||||||
<n-icon v-if="sort==='1'" :component="CaretUp"/>
|
|
||||||
</n-th>
|
|
||||||
<n-th>行业5日涨幅</n-th>
|
<n-th>行业5日涨幅</n-th>
|
||||||
<n-th>行业20日涨幅</n-th>
|
<n-th>行业20日涨幅</n-th>
|
||||||
<n-th>领涨股</n-th>
|
<n-th>领涨股</n-th>
|
||||||
@ -439,86 +397,16 @@ function ReFlesh(source) {
|
|||||||
</n-thead>
|
</n-thead>
|
||||||
<n-tbody>
|
<n-tbody>
|
||||||
<n-tr v-for="item in industryRanks" :key="item.bd_code">
|
<n-tr v-for="item in industryRanks" :key="item.bd_code">
|
||||||
<n-td>
|
<n-td><n-tag :bordered=false type="info">{{ item.bd_name }}</n-tag></n-td>
|
||||||
<n-tag :bordered=false type="info">{{ item.bd_name }}</n-tag>
|
<n-td><n-text :type="item.bd_zdf>0?'error':'success'">{{item.bd_zdf}}%</n-text></n-td>
|
||||||
</n-td>
|
<n-td><n-text :type="item.bd_zdf5>0?'error':'success'">{{item.bd_zdf5}}%</n-text></n-td>
|
||||||
<n-td>
|
<n-td><n-text :type="item.bd_zdf20>0?'error':'success'">{{item.bd_zdf20}}%</n-text></n-td>
|
||||||
<n-text :type="item.bd_zdf>0?'error':'success'">{{ item.bd_zdf }}%</n-text>
|
<n-td><n-text :type="item.nzg_zdf>0?'error':'success'"> {{item.nzg_name}} <n-text type="info">{{item.nzg_code}}</n-text></n-text></n-td>
|
||||||
</n-td>
|
<n-td><n-text :type="item.nzg_zdf>0?'error':'success'"> {{item.nzg_zdf}}%</n-text></n-td>
|
||||||
<n-td>
|
<n-td> <n-text :type="item.nzg_zdf>0?'error':'success'">{{item.nzg_zxj}}</n-text></n-td>
|
||||||
<n-text :type="item.bd_zdf5>0?'error':'success'">{{ item.bd_zdf5 }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.bd_zdf20>0?'error':'success'">{{ item.bd_zdf20 }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.nzg_zdf>0?'error':'success'"> {{ item.nzg_name }}
|
|
||||||
<n-text type="info">{{ item.nzg_code }}</n-text>
|
|
||||||
</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.nzg_zdf>0?'error':'success'"> {{ item.nzg_zdf }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.nzg_zdf>0?'error':'success'">{{ item.nzg_zxj }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
</n-tr>
|
</n-tr>
|
||||||
</n-tbody>
|
</n-tbody>
|
||||||
</n-table>
|
</n-table>
|
||||||
<n-table striped>
|
|
||||||
<n-thead>
|
|
||||||
<n-tr>
|
|
||||||
<n-th>行业名称</n-th>
|
|
||||||
<n-th @click="changeIndustryRankSort">行业涨幅
|
|
||||||
<n-icon v-if="sort==='0'" :component="CaretDown"/>
|
|
||||||
<n-icon v-if="sort==='1'" :component="CaretUp"/>
|
|
||||||
</n-th>
|
|
||||||
<n-th>行业5日涨幅</n-th>
|
|
||||||
<n-th>行业20日涨幅</n-th>
|
|
||||||
<n-th>领涨股</n-th>
|
|
||||||
<n-th>涨幅</n-th>
|
|
||||||
<n-th>最新价</n-th>
|
|
||||||
</n-tr>
|
|
||||||
</n-thead>
|
|
||||||
<n-tbody>
|
|
||||||
<n-tr v-for="item in industryRanks" :key="item.bd_code">
|
|
||||||
<n-td>
|
|
||||||
<n-tag :bordered=false type="info">{{ item.bd_name }}</n-tag>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.bd_zdf>0?'error':'success'">{{ item.bd_zdf }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.bd_zdf5>0?'error':'success'">{{ item.bd_zdf5 }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.bd_zdf20>0?'error':'success'">{{ item.bd_zdf20 }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.nzg_zdf>0?'error':'success'"> {{ item.nzg_name }}
|
|
||||||
<n-text type="info">{{ item.nzg_code }}</n-text>
|
|
||||||
</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.nzg_zdf>0?'error':'success'"> {{ item.nzg_zdf }}%</n-text>
|
|
||||||
</n-td>
|
|
||||||
<n-td>
|
|
||||||
<n-text :type="item.nzg_zdf>0?'error':'success'">{{ item.nzg_zxj }}</n-text>
|
|
||||||
</n-td>
|
|
||||||
</n-tr>
|
|
||||||
</n-tbody>
|
|
||||||
</n-table>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="行业资金排名(净流入)" tab="行业资金排名">
|
|
||||||
<industryMoneyRank :fenlei="'0'" :header-title="'行业资金排名(净流入)'" :sort="'netamount'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="证监会行业资金排名(净流入)" tab="证监会行业资金排名">
|
|
||||||
<industryMoneyRank :fenlei="'2'" :header-title="'证监会行业资金排名(净流入)'" :sort="'netamount'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="概念板块资金排名(净流入)" tab="概念板块资金排名">
|
|
||||||
<industryMoneyRank :fenlei="'1'" :header-title="'概念板块资金排名(净流入)'" :sort="'netamount'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
</n-tabs>
|
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="个股资金流向" tab="个股资金流向">
|
<n-tab-pane name="个股资金流向" tab="个股资金流向">
|
||||||
<n-tabs type="card" animated>
|
<n-tabs type="card" animated>
|
||||||
@ -551,57 +439,9 @@ function ReFlesh(source) {
|
|||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="龙虎榜" tab="龙虎榜">
|
|
||||||
<LongTigerRankList />
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="个股研报" tab="个股研报">
|
|
||||||
<StockResearchReportList :stock-code="stockCode"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="公司公告" tab="公司公告 ">
|
|
||||||
<StockNoticeList :stock-code="stockCode" />
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="行业研究" tab="行业研究 ">
|
|
||||||
<IndustryResearchReportList/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="当前热门" tab="当前热门">
|
|
||||||
<n-tabs type="card" animated>
|
|
||||||
<n-tab-pane name="全球" tab="全球">
|
|
||||||
<HotStockList :market-type="'10'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="沪深" tab="沪深">
|
|
||||||
<HotStockList :market-type="'12'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="港股" tab="港股">
|
|
||||||
<HotStockList :market-type="'13'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="美股" tab="美股">
|
|
||||||
<HotStockList :market-type="'11'"/>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="热门话题" tab="热门话题">
|
|
||||||
<n-grid :cols="1" :y-gap="10">
|
|
||||||
<n-grid-item>
|
|
||||||
<HotTopics/>
|
|
||||||
</n-grid-item>
|
|
||||||
<!-- <n-grid-item>-->
|
|
||||||
<!-- <HotEvents/>-->
|
|
||||||
<!-- </n-grid-item>-->
|
|
||||||
</n-grid>
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="重大事件时间轴" tab="重大事件时间轴">
|
|
||||||
<InvestCalendarTimeLine />
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="财经日历" tab="财经日历">
|
|
||||||
<ClsCalendarTimeLine />
|
|
||||||
</n-tab-pane>
|
|
||||||
</n-tabs>
|
|
||||||
</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;" :title="'AI市场资讯总结'" >
|
||||||
:title="'AI市场资讯总结'">
|
|
||||||
<n-spin size="small" :show="loading">
|
<n-spin size="small" :show="loading">
|
||||||
<MdPreview style="height: 440px;text-align: left" :modelValue="aiSummary" :theme="theme"/>
|
<MdPreview style="height: 440px;text-align: left" :modelValue="aiSummary" :theme="theme"/>
|
||||||
</n-spin>
|
</n-spin>
|
||||||
@ -616,10 +456,8 @@ function ReFlesh(source) {
|
|||||||
</template>
|
</template>
|
||||||
<template #action>
|
<template #action>
|
||||||
<n-flex justify="space-between" style="margin-bottom: 10px">
|
<n-flex justify="space-between" style="margin-bottom: 10px">
|
||||||
<n-select style="width: 49%" v-model:value="sysPromptId" label-field="name" value-field="ID"
|
<n-select style="width: 49%" v-model:value="sysPromptId" label-field="name" value-field="ID" :options="sysPromptOptions" placeholder="请选择系统提示词" />
|
||||||
:options="sysPromptOptions" placeholder="请选择系统提示词"/>
|
<n-select style="width: 49%" v-model:value="question" label-field="name" value-field="content" :options="userPromptOptions" placeholder="请选择用户提示词" />
|
||||||
<n-select style="width: 49%" v-model:value="question" label-field="name" value-field="content"
|
|
||||||
:options="userPromptOptions" placeholder="请选择用户提示词"/>
|
|
||||||
</n-flex>
|
</n-flex>
|
||||||
<n-flex justify="right">
|
<n-flex justify="right">
|
||||||
<n-input v-model:value="question" style="text-align: left" clearable
|
<n-input v-model:value="question" style="text-align: left" clearable
|
||||||
@ -647,8 +485,6 @@ function ReFlesh(source) {
|
|||||||
</n-input-group>
|
</n-input-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
|
@ -1,374 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {onMounted, ref} from "vue";
|
|
||||||
import {GetStockMoneyTrendByDay} from "../../wailsjs/go/main/App";
|
|
||||||
import * as echarts from "echarts";
|
|
||||||
|
|
||||||
const {code, name, darkTheme, days, chartHeight} = defineProps({
|
|
||||||
code: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
days: {
|
|
||||||
type: Number,
|
|
||||||
default: 14
|
|
||||||
},
|
|
||||||
chartHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: 500
|
|
||||||
},
|
|
||||||
darkTheme: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const LineChartRef = ref(null);
|
|
||||||
|
|
||||||
onMounted(
|
|
||||||
() => {
|
|
||||||
handleLine(code, days)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const handleLine = (code, days) => {
|
|
||||||
GetStockMoneyTrendByDay(code, days).then(result => {
|
|
||||||
//console.log("GetStockMoneyTrendByDay", result)
|
|
||||||
const chart = echarts.init(LineChartRef.value);
|
|
||||||
const categoryData = [];
|
|
||||||
const netamount_values = [];
|
|
||||||
const r0_net_values = [];
|
|
||||||
const trades_values = [];
|
|
||||||
let volume = []
|
|
||||||
|
|
||||||
let min = 0
|
|
||||||
let max = 0
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
|
||||||
let resultElement = result[i]
|
|
||||||
categoryData.push(resultElement.opendate)
|
|
||||||
let netamount = (resultElement.netamount / 10000).toFixed(2);
|
|
||||||
netamount_values.push(netamount)
|
|
||||||
let price = Number(resultElement.trade);
|
|
||||||
trades_values.push(price)
|
|
||||||
r0_net_values.push((resultElement.r0_net / 10000).toFixed(2))
|
|
||||||
|
|
||||||
if (min === 0 || min > price) {
|
|
||||||
min = price
|
|
||||||
}
|
|
||||||
if (max < price) {
|
|
||||||
max = price
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
let b = Number(Number(result[i].netamount) + Number(result[i - 1].netamount)) / 10000
|
|
||||||
volume.push(b.toFixed(2))
|
|
||||||
} else {
|
|
||||||
volume.push((Number(result[i].netamount) / 10000).toFixed(2))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
//console.log("volume", volume)
|
|
||||||
const upColor = '#ec0000';
|
|
||||||
const downColor = '#00da3c';
|
|
||||||
let option = {
|
|
||||||
title: {
|
|
||||||
text: name,
|
|
||||||
left: '20px',
|
|
||||||
textStyle: {
|
|
||||||
color: darkTheme?'#ccc':'#456'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
type: 'cross',
|
|
||||||
lineStyle: {
|
|
||||||
color: '#376df4',
|
|
||||||
width: 1,
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: darkTheme?'#456':'#ccc',
|
|
||||||
backgroundColor: darkTheme?'#456':'#fff',
|
|
||||||
padding: 10,
|
|
||||||
textStyle: {
|
|
||||||
color: darkTheme?'#ccc':'#456'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisPointer: {
|
|
||||||
link: [
|
|
||||||
{
|
|
||||||
xAxisIndex: 'all'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
label: {
|
|
||||||
backgroundColor: '#888'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
show: true,
|
|
||||||
data: ['当日净流入', '主力当日净流入','累计净流入', '股价'],
|
|
||||||
selected: {
|
|
||||||
'当日净流入': true,
|
|
||||||
'主力当日净流入': true,
|
|
||||||
'累计净流入': true,
|
|
||||||
'股价': true,
|
|
||||||
},
|
|
||||||
//orient: 'vertical',
|
|
||||||
textStyle: {
|
|
||||||
color: darkTheme ? 'rgb(253,252,252)' : '#456'
|
|
||||||
},
|
|
||||||
right: 150,
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
type: 'inside',
|
|
||||||
xAxisIndex: [0, 1],
|
|
||||||
start: 86,
|
|
||||||
end: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
show: true,
|
|
||||||
xAxisIndex: [0, 1],
|
|
||||||
type: 'slider',
|
|
||||||
top: '90%',
|
|
||||||
start: 86,
|
|
||||||
end: 100
|
|
||||||
}
|
|
||||||
],
|
|
||||||
grid: [
|
|
||||||
{
|
|
||||||
left: '8%',
|
|
||||||
right: '8%',
|
|
||||||
height: '50%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
left: '8%',
|
|
||||||
right: '8%',
|
|
||||||
top: '74%',
|
|
||||||
height: '15%'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
xAxis: [
|
|
||||||
{
|
|
||||||
type: 'category',
|
|
||||||
data: categoryData,
|
|
||||||
axisPointer: {
|
|
||||||
z: 100
|
|
||||||
},
|
|
||||||
|
|
||||||
boundaryGap: false,
|
|
||||||
axisLine: { onZero: false },
|
|
||||||
splitLine: { show: false },
|
|
||||||
min: 'dataMin',
|
|
||||||
max: 'dataMax',
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gridIndex: 1,
|
|
||||||
type: 'category',
|
|
||||||
data: categoryData,
|
|
||||||
axisLabel: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
name: '当日净流入/万',
|
|
||||||
type: 'value',
|
|
||||||
axisLine: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '股价',
|
|
||||||
type: 'value',
|
|
||||||
min: min - 1,
|
|
||||||
max: max + 1,
|
|
||||||
minInterval: 0.01,
|
|
||||||
axisLine: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gridIndex: 1,
|
|
||||||
name: '累计净流入/万',
|
|
||||||
type: 'value',
|
|
||||||
axisLine: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
yAxisIndex: 0,
|
|
||||||
name: '当日净流入',
|
|
||||||
data: netamount_values,
|
|
||||||
smooth: false,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
width: 2
|
|
||||||
},
|
|
||||||
markPoint: {
|
|
||||||
symbol: 'arrow',
|
|
||||||
symbolRotate: 90,
|
|
||||||
symbolSize: [10, 20],
|
|
||||||
symbolOffset: [10, 0],
|
|
||||||
itemStyle: {
|
|
||||||
color: '#0d7dfc'
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
position: 'right',
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{type: 'max', name: 'Max'},
|
|
||||||
{type: 'min', name: 'Min'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
markLine: {
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
type: 'average',
|
|
||||||
name: 'Average',
|
|
||||||
lineStyle: {
|
|
||||||
color: '#0077ff',
|
|
||||||
width: 0.5
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
type: 'line'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxisIndex: 0,
|
|
||||||
name: '主力当日净流入',
|
|
||||||
data: r0_net_values,
|
|
||||||
smooth: false,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
width: 2
|
|
||||||
},
|
|
||||||
// markPoint: {
|
|
||||||
// symbol: 'arrow',
|
|
||||||
// symbolRotate: 90,
|
|
||||||
// symbolSize: [10, 20],
|
|
||||||
// symbolOffset: [10, 0],
|
|
||||||
// itemStyle: {
|
|
||||||
// color: '#0d7dfc'
|
|
||||||
// },
|
|
||||||
// label: {
|
|
||||||
// position: 'right',
|
|
||||||
// },
|
|
||||||
// data: [
|
|
||||||
// {type: 'max', name: 'Max'},
|
|
||||||
// {type: 'min', name: 'Min'}
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
// markLine: {
|
|
||||||
// data: [
|
|
||||||
// {
|
|
||||||
// type: 'average',
|
|
||||||
// name: 'Average',
|
|
||||||
// lineStyle: {
|
|
||||||
// color: '#0077ff',
|
|
||||||
// width: 0.5
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
type: 'bar'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxisIndex: 1,
|
|
||||||
name: '股价',
|
|
||||||
type: 'line',
|
|
||||||
data: trades_values,
|
|
||||||
smooth: true,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
width: 3
|
|
||||||
},
|
|
||||||
markPoint: {
|
|
||||||
symbol: 'arrow',
|
|
||||||
symbolRotate: 90,
|
|
||||||
symbolSize: [10, 20],
|
|
||||||
symbolOffset: [10, 0],
|
|
||||||
itemStyle: {
|
|
||||||
color: '#f39509'
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
position: 'right',
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{type: 'max', name: 'Max'},
|
|
||||||
{type: 'min', name: 'Min'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
markLine: {
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
type: 'average',
|
|
||||||
name: 'Average',
|
|
||||||
lineStyle: {
|
|
||||||
color: '#f39509',
|
|
||||||
width: 0.5
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'bar',
|
|
||||||
xAxisIndex: 1,
|
|
||||||
yAxisIndex: 2,
|
|
||||||
name: '累计净流入',
|
|
||||||
data: volume,
|
|
||||||
smooth: true,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
width: 2
|
|
||||||
},
|
|
||||||
markPoint: {
|
|
||||||
symbol: 'arrow',
|
|
||||||
symbolRotate: 90,
|
|
||||||
symbolSize: [10, 20],
|
|
||||||
symbolOffset: [10, 0],
|
|
||||||
// itemStyle: {
|
|
||||||
// color: '#f39509'
|
|
||||||
// },
|
|
||||||
label: {
|
|
||||||
position: 'right',
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{type: 'max', name: 'Max'},
|
|
||||||
{type: 'min', name: 'Min'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
};
|
|
||||||
chart.setOption(option);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div ref="LineChartRef" style="width: 100%;height: auto;" :style="{height:chartHeight+'px'}"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,10 +1,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import {CaretDown, CaretUp, RefreshCircleOutline} from "@vicons/ionicons5";
|
import {CaretDown, CaretUp} from "@vicons/ionicons5";
|
||||||
import {NText,useMessage} from "naive-ui";
|
import {NText} from "naive-ui";
|
||||||
import {onBeforeUnmount, onMounted, onUnmounted, ref} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {GetMoneyRankSina} from "../../wailsjs/go/main/App";
|
import {GetMoneyRankSina} from "../../wailsjs/go/main/App";
|
||||||
import KLineChart from "./KLineChart.vue";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
headerTitle: {
|
headerTitle: {
|
||||||
@ -16,22 +15,16 @@ const props = defineProps({
|
|||||||
default: 'netamount'
|
default: 'netamount'
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const message = useMessage()
|
|
||||||
const dataList= ref([])
|
const dataList= ref([])
|
||||||
const sort = ref(props.sort)
|
const sort = ref(props.sort)
|
||||||
const interval = ref(null)
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
sort.value=props.sort
|
sort.value=props.sort
|
||||||
GetMoneyRankSinaData()
|
GetMoneyRankSinaData()
|
||||||
interval.value=setInterval(()=>{
|
setInterval(()=>{
|
||||||
GetMoneyRankSinaData()
|
GetMoneyRankSinaData()
|
||||||
},1000*60)
|
},1000*60)
|
||||||
})
|
})
|
||||||
onBeforeUnmount(()=>{
|
|
||||||
clearInterval(interval.value)
|
|
||||||
})
|
|
||||||
function GetMoneyRankSinaData(){
|
function GetMoneyRankSinaData(){
|
||||||
message.loading("正在刷新数据...")
|
|
||||||
GetMoneyRankSina(sort.value).then(result => {
|
GetMoneyRankSina(sort.value).then(result => {
|
||||||
if(result.length>0){
|
if(result.length>0){
|
||||||
dataList.value = result
|
dataList.value = result
|
||||||
@ -67,15 +60,8 @@ function GetMoneyRankSinaData(){
|
|||||||
<n-tbody>
|
<n-tbody>
|
||||||
<n-tr v-for="item in dataList" :key="item.symbol">
|
<n-tr v-for="item in dataList" :key="item.symbol">
|
||||||
<n-td><n-tag :bordered=false type="info">{{ item.symbol }}</n-tag></n-td>
|
<n-td><n-tag :bordered=false type="info">{{ item.symbol }}</n-tag></n-td>
|
||||||
<n-td>
|
<n-td><n-tag :bordered=false type="info">{{ item.name }}</n-tag></n-td>
|
||||||
<n-popover trigger="hover" placement="right">
|
<n-td><n-text :type="item.trade>0?'error':'success'">{{item.trade}}</n-text></n-td>
|
||||||
<template #trigger>
|
|
||||||
<n-button tag="a" text :type="item.changeratio>0?'error':'success'" :bordered=false >{{ item.name }}</n-button>
|
|
||||||
</template>
|
|
||||||
<k-line-chart style="width: 800px" :code="item.symbol" :chart-height="500" :name="item.name" :k-days="20" :dark-theme="true"></k-line-chart>
|
|
||||||
</n-popover>
|
|
||||||
</n-td>
|
|
||||||
<n-td><n-text :type="item.changeratio>0?'error':'success'">{{item.trade}}</n-text></n-td>
|
|
||||||
<n-td><n-text :type="item.changeratio>0?'error':'success'">{{(item.changeratio*100).toFixed(2)}}%</n-text></n-td>
|
<n-td><n-text :type="item.changeratio>0?'error':'success'">{{(item.changeratio*100).toFixed(2)}}%</n-text></n-td>
|
||||||
<n-td><n-text :type="item.turnover>500?'error':'info'">{{(item.turnover/100).toFixed(2)}}%</n-text></n-td>
|
<n-td><n-text :type="item.turnover>500?'error':'info'">{{(item.turnover/100).toFixed(2)}}%</n-text></n-td>
|
||||||
<n-td><n-text type="info">{{(item.amount/10000).toFixed(2)}}</n-text></n-td>
|
<n-td><n-text type="info">{{(item.amount/10000).toFixed(2)}}</n-text></n-td>
|
||||||
|
@ -45,7 +45,6 @@ const formValue = ref({
|
|||||||
enableNews:false,
|
enableNews:false,
|
||||||
darkTheme:true,
|
darkTheme:true,
|
||||||
enableFund:false,
|
enableFund:false,
|
||||||
enablePushNews:false,
|
|
||||||
})
|
})
|
||||||
const promptTemplates=ref([])
|
const promptTemplates=ref([])
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
@ -79,14 +78,13 @@ onMounted(()=>{
|
|||||||
formValue.value.enableNews = res.enableNews
|
formValue.value.enableNews = res.enableNews
|
||||||
formValue.value.darkTheme = res.darkTheme
|
formValue.value.darkTheme = res.darkTheme
|
||||||
formValue.value.enableFund = res.enableFund
|
formValue.value.enableFund = res.enableFund
|
||||||
formValue.value.enablePushNews = res.enablePushNews
|
|
||||||
|
|
||||||
//console.log(res)
|
console.log(res)
|
||||||
})
|
})
|
||||||
//message.info("加载完成")
|
//message.info("加载完成")
|
||||||
|
|
||||||
GetPromptTemplates("","").then(res=>{
|
GetPromptTemplates("","").then(res=>{
|
||||||
//console.log(res)
|
console.log(res)
|
||||||
promptTemplates.value=res
|
promptTemplates.value=res
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -120,7 +118,6 @@ function saveConfig(){
|
|||||||
enableNews:formValue.value.enableNews,
|
enableNews:formValue.value.enableNews,
|
||||||
darkTheme:formValue.value.darkTheme,
|
darkTheme:formValue.value.darkTheme,
|
||||||
enableFund:formValue.value.enableFund,
|
enableFund:formValue.value.enableFund,
|
||||||
enablePushNews:formValue.value.enablePushNews
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -168,7 +165,7 @@ function importConfig(){
|
|||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
let config = JSON.parse(e.target.result);
|
let config = JSON.parse(e.target.result);
|
||||||
//console.log(config)
|
console.log(config)
|
||||||
formValue.value.ID = config.ID
|
formValue.value.ID = config.ID
|
||||||
formValue.value.tushareToken = config.tushareToken
|
formValue.value.tushareToken = config.tushareToken
|
||||||
formValue.value.dingPush = {
|
formValue.value.dingPush = {
|
||||||
@ -198,7 +195,6 @@ function importConfig(){
|
|||||||
formValue.value.enableNews = config.enableNews
|
formValue.value.enableNews = config.enableNews
|
||||||
formValue.value.darkTheme = config.darkTheme
|
formValue.value.darkTheme = config.darkTheme
|
||||||
formValue.value.enableFund = config.enableFund
|
formValue.value.enableFund = config.enableFund
|
||||||
formValue.value.enablePushNews = config.enablePushNews
|
|
||||||
// formRef.value.resetFields()
|
// formRef.value.resetFields()
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
@ -208,7 +204,7 @@ function importConfig(){
|
|||||||
|
|
||||||
|
|
||||||
window.onerror = function (event, source, lineno, colno, error) {
|
window.onerror = function (event, source, lineno, colno, error) {
|
||||||
//console.log(event, source, lineno, colno, error)
|
console.log(event, source, lineno, colno, error)
|
||||||
// 将错误信息发送给后端
|
// 将错误信息发送给后端
|
||||||
EventsEmit("frontendError", {
|
EventsEmit("frontendError", {
|
||||||
page: "settings.vue",
|
page: "settings.vue",
|
||||||
@ -241,14 +237,14 @@ function savePrompt(){
|
|||||||
AddPrompt(formPrompt.value).then(res=>{
|
AddPrompt(formPrompt.value).then(res=>{
|
||||||
message.success(res)
|
message.success(res)
|
||||||
GetPromptTemplates("","").then(res=>{
|
GetPromptTemplates("","").then(res=>{
|
||||||
//console.log(res)
|
console.log(res)
|
||||||
promptTemplates.value=res
|
promptTemplates.value=res
|
||||||
})
|
})
|
||||||
showManagePromptsModal.value=false
|
showManagePromptsModal.value=false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function editPrompt(prompt){
|
function editPrompt(prompt){
|
||||||
//console.log(prompt)
|
console.log(prompt)
|
||||||
formPrompt.value.ID=prompt.ID
|
formPrompt.value.ID=prompt.ID
|
||||||
formPrompt.value.Name=prompt.name
|
formPrompt.value.Name=prompt.name
|
||||||
formPrompt.value.Content=prompt.content
|
formPrompt.value.Content=prompt.content
|
||||||
@ -259,7 +255,7 @@ function deletePrompt(ID){
|
|||||||
DelPrompt(ID).then(res=>{
|
DelPrompt(ID).then(res=>{
|
||||||
message.success(res)
|
message.success(res)
|
||||||
GetPromptTemplates("","").then(res=>{
|
GetPromptTemplates("","").then(res=>{
|
||||||
//console.log(res)
|
console.log(res)
|
||||||
promptTemplates.value=res
|
promptTemplates.value=res
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -292,7 +288,7 @@ function deletePrompt(ID){
|
|||||||
<n-form-item-gi :span="10" label="浏览器安装路径:" path="browserPath" >
|
<n-form-item-gi :span="10" label="浏览器安装路径:" path="browserPath" >
|
||||||
<n-input type="text" placeholder="浏览器安装路径" v-model:value="formValue.browserPath" clearable />
|
<n-input type="text" placeholder="浏览器安装路径" v-model:value="formValue.browserPath" clearable />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="6" label="指数基金:" path="enableFund" >
|
<n-form-item-gi :span="6" label="是否启用指数基金:" path="enableFund" >
|
||||||
<n-switch v-model:value="formValue.enableFund" />
|
<n-switch v-model:value="formValue.enableFund" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
@ -301,21 +297,18 @@ function deletePrompt(ID){
|
|||||||
<n-gi :span="24">
|
<n-gi :span="24">
|
||||||
<n-text type="success" style="font-size: 25px;font-weight: bold">通知设置</n-text>
|
<n-text type="success" style="font-size: 25px;font-weight: bold">通知设置</n-text>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
<n-form-item-gi :span="4" label="钉钉推送:" path="dingPush.enable" >
|
<n-form-item-gi :span="6" label="是否启用钉钉推送:" path="dingPush.enable" >
|
||||||
<n-switch v-model:value="formValue.dingPush.enable" />
|
<n-switch v-model:value="formValue.dingPush.enable" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="4" label="本地推送:" path="localPush.enable" >
|
<n-form-item-gi :span="6" label="是否启用本地推送:" path="localPush.enable" >
|
||||||
<n-switch v-model:value="formValue.localPush.enable" />
|
<n-switch v-model:value="formValue.localPush.enable" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="4" label="弹幕功能:" path="enableDanmu" >
|
<n-form-item-gi :span="5" label="弹幕功能:" path="enableDanmu" >
|
||||||
<n-switch v-model:value="formValue.enableDanmu" />
|
<n-switch v-model:value="formValue.enableDanmu" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="4" label="显示滚动快讯:" path="enableNews" >
|
<n-form-item-gi :span="5" label="是否显示滚动快讯(重启生效):" path="enableNews" >
|
||||||
<n-switch v-model:value="formValue.enableNews" />
|
<n-switch v-model:value="formValue.enableNews" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="4" label="市场资讯提醒:" path="enablePushNews" >
|
|
||||||
<n-switch v-model:value="formValue.enablePushNews" />
|
|
||||||
</n-form-item-gi>
|
|
||||||
<n-form-item-gi :span="22" v-if="formValue.dingPush.enable" label="钉钉机器人接口地址:" path="dingPush.dingRobot" >
|
<n-form-item-gi :span="22" v-if="formValue.dingPush.enable" label="钉钉机器人接口地址:" path="dingPush.dingRobot" >
|
||||||
<n-input placeholder="请输入钉钉机器人接口地址" v-model:value="formValue.dingPush.dingRobot"/>
|
<n-input placeholder="请输入钉钉机器人接口地址" v-model:value="formValue.dingPush.dingRobot"/>
|
||||||
<n-button type="primary" @click="sendTestNotice">发送测试通知</n-button>
|
<n-button type="primary" @click="sendTestNotice">发送测试通知</n-button>
|
||||||
@ -326,7 +319,7 @@ function deletePrompt(ID){
|
|||||||
<n-gi :span="24">
|
<n-gi :span="24">
|
||||||
<n-text type="success" style="font-size: 25px;font-weight: bold">OpenAI设置</n-text>
|
<n-text type="success" style="font-size: 25px;font-weight: bold">OpenAI设置</n-text>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
<n-form-item-gi :span="3" label="AI诊股:" path="openAI.enable" >
|
<n-form-item-gi :span="3" label="是否启用AI诊股:" path="openAI.enable" >
|
||||||
<n-switch v-model:value="formValue.openAI.enable" />
|
<n-switch v-model:value="formValue.openAI.enable" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="9" v-if="formValue.openAI.enable" label="openAI 接口地址:" path="openAI.baseUrl" >
|
<n-form-item-gi :span="9" v-if="formValue.openAI.enable" label="openAI 接口地址:" path="openAI.baseUrl" >
|
||||||
|
@ -2,31 +2,28 @@
|
|||||||
import {computed, h, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
import {computed, h, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import {
|
import {
|
||||||
AddGroup,
|
|
||||||
AddStockGroup,
|
|
||||||
Follow,
|
Follow,
|
||||||
GetAIResponseResult,
|
GetAIResponseResult,
|
||||||
GetConfig,
|
GetConfig,
|
||||||
GetFollowList,
|
GetFollowList,
|
||||||
GetGroupList,
|
|
||||||
GetPromptTemplates,
|
|
||||||
GetStockKLine,
|
|
||||||
GetStockList,
|
GetStockList,
|
||||||
GetStockMinutePriceLineData,
|
|
||||||
GetVersionInfo,
|
GetVersionInfo,
|
||||||
Greet,
|
Greet,
|
||||||
NewChatStream,
|
NewChatStream,
|
||||||
RemoveGroup,
|
|
||||||
RemoveStockGroup,
|
|
||||||
SaveAIResponseResult,
|
SaveAIResponseResult,
|
||||||
SaveAsMarkdown,
|
|
||||||
SendDingDingMessageByType,
|
SendDingDingMessageByType,
|
||||||
SetAlarmChangePercent,
|
SetAlarmChangePercent,
|
||||||
SetCostPriceAndVolume,
|
SetCostPriceAndVolume,
|
||||||
SetStockAICron,
|
|
||||||
SetStockSort,
|
SetStockSort,
|
||||||
|
UnFollow,
|
||||||
ShareAnalysis,
|
ShareAnalysis,
|
||||||
UnFollow
|
SaveAsMarkdown,
|
||||||
|
GetPromptTemplates,
|
||||||
|
SetStockAICron,
|
||||||
|
AddGroup,
|
||||||
|
GetGroupList,
|
||||||
|
AddStockGroup,
|
||||||
|
RemoveStockGroup, RemoveGroup, GetStockKLine, GetStockMinutePriceLineData
|
||||||
} from '../../wailsjs/go/main/App'
|
} from '../../wailsjs/go/main/App'
|
||||||
import {
|
import {
|
||||||
NAvatar,
|
NAvatar,
|
||||||
@ -38,6 +35,7 @@ import {
|
|||||||
NText,
|
NText,
|
||||||
useDialog,
|
useDialog,
|
||||||
useMessage,
|
useMessage,
|
||||||
|
useModal,
|
||||||
useNotification
|
useNotification
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import {
|
import {
|
||||||
@ -48,8 +46,11 @@ import {
|
|||||||
WindowReload,
|
WindowReload,
|
||||||
WindowUnfullscreen
|
WindowUnfullscreen
|
||||||
} from '../../wailsjs/runtime'
|
} from '../../wailsjs/runtime'
|
||||||
import {Add, ChatboxOutline,} from '@vicons/ionicons5'
|
import {
|
||||||
import {MdEditor, MdPreview} from 'md-editor-v3';
|
Add,
|
||||||
|
ChatboxOutline,
|
||||||
|
} from '@vicons/ionicons5'
|
||||||
|
import {MdPreview,MdEditor } from 'md-editor-v3';
|
||||||
// preview.css相比style.css少了编辑器那部分样式
|
// preview.css相比style.css少了编辑器那部分样式
|
||||||
//import 'md-editor-v3/lib/preview.css';
|
//import 'md-editor-v3/lib/preview.css';
|
||||||
import 'md-editor-v3/lib/style.css';
|
import 'md-editor-v3/lib/style.css';
|
||||||
@ -60,12 +61,11 @@ import html2canvas from "html2canvas";
|
|||||||
import {asBlob} from 'html-docx-js-typescript';
|
import {asBlob} from 'html-docx-js-typescript';
|
||||||
|
|
||||||
import vueDanmaku from 'vue3-danmaku'
|
import vueDanmaku from 'vue3-danmaku'
|
||||||
import {keys, padStart} from "lodash";
|
import {keys, pad, padStart} from "lodash";
|
||||||
import {useRoute, useRouter} from 'vue-router'
|
import {models} from "../../wailsjs/go/models";
|
||||||
import MoneyTrend from "./moneyTrend.vue";
|
import {RouterLink} from "vue-router";
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
const danmus = ref([])
|
const danmus = ref([])
|
||||||
const ws = ref(null)
|
const ws = ref(null)
|
||||||
@ -99,7 +99,6 @@ const modalShow = ref(false)
|
|||||||
const modalShow2 = ref(false)
|
const modalShow2 = ref(false)
|
||||||
const modalShow3 = ref(false)
|
const modalShow3 = ref(false)
|
||||||
const modalShow4 = ref(false)
|
const modalShow4 = ref(false)
|
||||||
const modalShow5 = ref(false)
|
|
||||||
const addBTN = ref(true)
|
const addBTN = ref(true)
|
||||||
const formModel = ref({
|
const formModel = ref({
|
||||||
name: "",
|
name: "",
|
||||||
@ -139,6 +138,7 @@ const feishiInterval = ref(null)
|
|||||||
const currentGroupId=ref(0)
|
const currentGroupId=ref(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const theme=computed(() => {
|
const theme=computed(() => {
|
||||||
return data.darkTheme ? 'dark' : 'light'
|
return data.darkTheme ? 'dark' : 'light'
|
||||||
})
|
})
|
||||||
@ -150,7 +150,9 @@ const danmakuColor = computed(() => {
|
|||||||
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');
|
||||||
|
|
||||||
const sortedResults = computed(() => {
|
const sortedResults = computed(() => {
|
||||||
|
////console.log("computed",sortedResults.value)
|
||||||
const sortedKeys =keys(results.value).sort();
|
const sortedKeys =keys(results.value).sort();
|
||||||
|
////console.log("sortedKeys",sortedKeys)
|
||||||
const sortedObject = {};
|
const sortedObject = {};
|
||||||
sortedKeys.forEach(key => {
|
sortedKeys.forEach(key => {
|
||||||
sortedObject[key] = results.value[key];
|
sortedObject[key] = results.value[key];
|
||||||
@ -167,7 +169,6 @@ const groupResults = computed(() => {
|
|||||||
}
|
}
|
||||||
return group
|
return group
|
||||||
})
|
})
|
||||||
const showPopover = ref(false)
|
|
||||||
|
|
||||||
onBeforeMount(()=>{
|
onBeforeMount(()=>{
|
||||||
GetGroupList().then(result => {
|
GetGroupList().then(result => {
|
||||||
@ -175,7 +176,7 @@ onBeforeMount(() => {
|
|||||||
if(route.query.groupId){
|
if(route.query.groupId){
|
||||||
message.success("切换分组:"+route.query.groupName)
|
message.success("切换分组:"+route.query.groupName)
|
||||||
currentGroupId.value=Number(route.query.groupId)
|
currentGroupId.value=Number(route.query.groupId)
|
||||||
//console.log("route.params",route.query)
|
console.log("route.params",route.query)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
GetStockList("").then(result => {
|
GetStockList("").then(result => {
|
||||||
@ -187,6 +188,20 @@ onBeforeMount(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
GetFollowList(currentGroupId.value).then(result => {
|
||||||
|
followList.value = result
|
||||||
|
for (const followedStock of result) {
|
||||||
|
if(followedStock.StockCode.startsWith("us")){
|
||||||
|
followedStock.StockCode="gb_"+ followedStock.StockCode.replace("us", "").toLowerCase()
|
||||||
|
}
|
||||||
|
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||||
|
////console.log("followList",followedStock.StockCode)
|
||||||
|
stocks.value.push(followedStock.StockCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
monitor()
|
||||||
|
message.destroyAll()
|
||||||
|
})
|
||||||
GetConfig().then(result => {
|
GetConfig().then(result => {
|
||||||
if (result.openAiEnable) {
|
if (result.openAiEnable) {
|
||||||
data.openAiEnable = true
|
data.openAiEnable = true
|
||||||
@ -212,22 +227,14 @@ onBeforeMount(() => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
message.loading("Loading...")
|
message.loading("Loading...")
|
||||||
|
// //console.log(`the component is now mounted.`)
|
||||||
|
|
||||||
GetFollowList(currentGroupId.value).then(result => {
|
// ticker.value=setInterval(() => {
|
||||||
|
// if(isTradingTime()){
|
||||||
followList.value = result
|
// //monitor()
|
||||||
for (const followedStock of result) {
|
// //data.fenshiURL='http://image.sinajs.cn/newchart/min/n/'+data.code+'.gif'+"?t="+Date.now()
|
||||||
if (followedStock.StockCode.startsWith("us")) {
|
// }
|
||||||
followedStock.StockCode = "gb_" + followedStock.StockCode.replace("us", "").toLowerCase()
|
// }, 3500)
|
||||||
}
|
|
||||||
if (!stocks.value.includes(followedStock.StockCode)) {
|
|
||||||
stocks.value.push(followedStock.StockCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
monitor()
|
|
||||||
message.destroyAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
GetVersionInfo().then((res) => {
|
GetVersionInfo().then((res) => {
|
||||||
icon.value = res.icon;
|
icon.value = res.icon;
|
||||||
@ -271,20 +278,6 @@ onBeforeUnmount(() => {
|
|||||||
EventsOff("changeTab")
|
EventsOff("changeTab")
|
||||||
EventsOff("updateVersion")
|
EventsOff("updateVersion")
|
||||||
EventsOff("warnMsg")
|
EventsOff("warnMsg")
|
||||||
EventsOff("loadingDone")
|
|
||||||
})
|
|
||||||
|
|
||||||
EventsOn("loadingDone", (data) => {
|
|
||||||
message.loading("刷新股票基础数据...")
|
|
||||||
GetStockList("").then(result => {
|
|
||||||
stockList.value = result
|
|
||||||
options.value = result.map(item => {
|
|
||||||
return {
|
|
||||||
label: item.name + " - " + item.ts_code,
|
|
||||||
value: item.ts_code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
EventsOn("refresh",(data)=>{
|
EventsOn("refresh",(data)=>{
|
||||||
@ -302,6 +295,17 @@ EventsOn("stock_price", (data) => {
|
|||||||
EventsOn("refreshFollowList",(data)=>{
|
EventsOn("refreshFollowList",(data)=>{
|
||||||
|
|
||||||
WindowReload()
|
WindowReload()
|
||||||
|
// message.loading("refresh...")
|
||||||
|
// GetFollowList().then(result => {
|
||||||
|
// followList.value = result
|
||||||
|
// for (const followedStock of result) {
|
||||||
|
// if (!stocks.value.includes(followedStock.StockCode)) {
|
||||||
|
// stocks.value.push(followedStock.StockCode)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// monitor()
|
||||||
|
// message.destroyAll
|
||||||
|
// })
|
||||||
})
|
})
|
||||||
|
|
||||||
EventsOn("newChatStream",async (msg) => {
|
EventsOn("newChatStream",async (msg) => {
|
||||||
@ -434,14 +438,8 @@ function AddStock() {
|
|||||||
if (!stocks.value.includes(data.code)) {
|
if (!stocks.value.includes(data.code)) {
|
||||||
Follow(data.code).then(result => {
|
Follow(data.code).then(result => {
|
||||||
if(result==="关注成功"){
|
if(result==="关注成功"){
|
||||||
if (data.code.startsWith("us")) {
|
|
||||||
data.code= "gb_" + data.code.replace("us", "").toLowerCase()
|
|
||||||
}
|
|
||||||
stocks.value.push(data.code)
|
stocks.value.push(data.code)
|
||||||
message.success(result)
|
message.success(result)
|
||||||
GetFollowList(currentGroupId.value).then(result => {
|
|
||||||
followList.value = result
|
|
||||||
})
|
|
||||||
monitor();
|
monitor();
|
||||||
}else{
|
}else{
|
||||||
message.error(result)
|
message.error(result)
|
||||||
@ -453,6 +451,7 @@ function AddStock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function removeMonitor(code,name,key) {
|
function removeMonitor(code,name,key) {
|
||||||
//console.log("removeMonitor",name,code,key)
|
//console.log("removeMonitor",name,code,key)
|
||||||
stocks.value.splice(stocks.value.indexOf(code),1)
|
stocks.value.splice(stocks.value.indexOf(code),1)
|
||||||
@ -478,6 +477,7 @@ function SendDanmu() {
|
|||||||
function getStockList(value){
|
function getStockList(value){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// //console.log("getStockList",value)
|
// //console.log("getStockList",value)
|
||||||
let result;
|
let result;
|
||||||
result=stockList.value.filter(item => item.name.includes(value)||item.ts_code.includes(value))
|
result=stockList.value.filter(item => item.name.includes(value)||item.ts_code.includes(value))
|
||||||
@ -502,12 +502,14 @@ function getStockList(value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function blinkBorder(findId){
|
function blinkBorder(findId){
|
||||||
// 获取要滚动到的元素
|
// 获取要滚动到的元素
|
||||||
let element = document.getElementById(findId);
|
let element = document.getElementById(findId);
|
||||||
//console.log("blinkBorder",findId,element)
|
console.log("blinkBorder",findId,element)
|
||||||
if (element) {
|
if (element) {
|
||||||
// 滚动到该元素
|
// 滚动到该元素
|
||||||
element.scrollIntoView({ behavior: 'smooth'});
|
element.scrollIntoView({ behavior: 'smooth'});
|
||||||
@ -563,25 +565,19 @@ async function updateData(result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//result.key=result.sort
|
//result.key=result.sort
|
||||||
results.value = Object.fromEntries(
|
|
||||||
Object.entries(results.value).filter(
|
|
||||||
([key]) => !key.includes(result["股票代码"])
|
|
||||||
));
|
|
||||||
|
|
||||||
result.key=GetSortKey(result.sort,result["股票代码"])
|
result.key=GetSortKey(result.sort,result["股票代码"])
|
||||||
results.value[result.key] = result
|
results.value[GetSortKey(result.sort,result["股票代码"])]=result
|
||||||
if(!stocks.value.includes(result["股票代码"])) {
|
if(!stocks.value.includes(result["股票代码"])) {
|
||||||
delete results.value[result.key]
|
delete results.value[result.key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////console.log("updateData",result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function monitor() {
|
async function monitor() {
|
||||||
if (stocks.value && stocks.value.length === 0) {
|
|
||||||
showPopover.value = true
|
|
||||||
}
|
|
||||||
for (let code of stocks.value) {
|
for (let code of stocks.value) {
|
||||||
|
// //console.log(code)
|
||||||
Greet(code).then(result => {
|
Greet(code).then(result => {
|
||||||
updateData(result)
|
updateData(result)
|
||||||
})
|
})
|
||||||
@ -591,6 +587,7 @@ async function monitor() {
|
|||||||
|
|
||||||
function GetSortKey(sort,code){
|
function GetSortKey(sort,code){
|
||||||
let sortKey= padStart(sort,8,'0')+"_"+code
|
let sortKey= padStart(sort,8,'0')+"_"+code
|
||||||
|
////console.log("GetSortKey:",sortKey)
|
||||||
return sortKey
|
return sortKey
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,31 +603,16 @@ function onSelect(item) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openCenteredWindow(url, width, height) {
|
|
||||||
const left = (window.screen.width - width) / 2;
|
|
||||||
const top = (window.screen.height - height) / 2;
|
|
||||||
|
|
||||||
return window.open(
|
|
||||||
url,
|
|
||||||
'centeredWindow',
|
|
||||||
`width=${width},height=${height},left=${left},top=${top}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function search(code,name){
|
function search(code,name){
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
//window.open("https://xueqiu.com/S/"+code)
|
//window.open("https://xueqiu.com/S/"+code)
|
||||||
//window.open("https://www.cls.cn/stock?code="+code)
|
//window.open("https://www.cls.cn/stock?code="+code)
|
||||||
//window.open("https://quote.eastmoney.com/"+code+".html")
|
//window.open("https://quote.eastmoney.com/"+code+".html")
|
||||||
//window.open("https://finance.sina.com.cn/realstock/company/"+code+"/nc.shtml")
|
//window.open("https://finance.sina.com.cn/realstock/company/"+code+"/nc.shtml")
|
||||||
//window.open("https://www.iwencai.com/unifiedwap/result?w=" + name)
|
window.open("https://www.iwencai.com/unifiedwap/result?w="+name)
|
||||||
//window.open("https://www.iwencai.com/chat/?question="+code)
|
//window.open("https://www.iwencai.com/chat/?question="+code)
|
||||||
|
|
||||||
openCenteredWindow("https://www.iwencai.com/unifiedwap/result?w=" + name,1000,800)
|
|
||||||
|
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setStock(code,name){
|
function setStock(code,name){
|
||||||
let res=followList.value.filter(item => item.StockCode===code)
|
let res=followList.value.filter(item => item.StockCode===code)
|
||||||
////console.log("res:",res)
|
////console.log("res:",res)
|
||||||
@ -644,12 +626,10 @@ function setStock(code, name) {
|
|||||||
formModel.value.cron=res[0].Cron
|
formModel.value.cron=res[0].Cron
|
||||||
modalShow.value=true
|
modalShow.value=true
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearFeishi(){
|
function clearFeishi(){
|
||||||
//console.log("clearFeishi")
|
console.log("clearFeishi")
|
||||||
clearInterval(feishiInterval.value)
|
clearInterval(feishiInterval.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function showFsChart(code, name) {
|
function showFsChart(code, name) {
|
||||||
data.name = name
|
data.name = name
|
||||||
data.code = code
|
data.code = code
|
||||||
@ -760,8 +740,8 @@ function showFsChart(code, name) {
|
|||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
name: "股价",
|
name: "股价",
|
||||||
min: (min - min * 0.01).toFixed(2),
|
min: min - 1,
|
||||||
max: (max + max * 0.01).toFixed(2),
|
max: max + 1,
|
||||||
minInterval: 0.01,
|
minInterval: 0.01,
|
||||||
type: 'value'
|
type: 'value'
|
||||||
},
|
},
|
||||||
@ -916,7 +896,6 @@ function calculateMA(dayCount, values) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKLine(){
|
function handleKLine(){
|
||||||
GetStockKLine(data.code,data.name,365).then(result => {
|
GetStockKLine(data.code,data.name,365).then(result => {
|
||||||
//console.log("GetStockKLine",result)
|
//console.log("GetStockKLine",result)
|
||||||
@ -1238,17 +1217,10 @@ function handleKLine() {
|
|||||||
};
|
};
|
||||||
chart.setOption(option);
|
chart.setOption(option);
|
||||||
chart.on('click',{seriesName:'日K'}, function(params) {
|
chart.on('click',{seriesName:'日K'}, function(params) {
|
||||||
//console.log("click:",params);
|
console.log("click:",params);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMoney(code, name) {
|
|
||||||
data.code = code
|
|
||||||
data.name = name
|
|
||||||
modalShow5.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
function showK(code,name){
|
function showK(code,name){
|
||||||
data.code=code
|
data.code=code
|
||||||
data.name=name
|
data.name=name
|
||||||
@ -1265,7 +1237,10 @@ function showK(code, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function updateCostPriceAndVolumeNew(code,price,volume,alarm,formModel){
|
function updateCostPriceAndVolumeNew(code,price,volume,alarm,formModel){
|
||||||
|
|
||||||
if(formModel.sort){
|
if(formModel.sort){
|
||||||
SetStockSort(formModel.sort,code).then(result => {
|
SetStockSort(formModel.sort,code).then(result => {
|
||||||
//message.success(result)
|
//message.success(result)
|
||||||
@ -1287,7 +1262,6 @@ function updateCostPriceAndVolumeNew(code, price, volume, alarm, formModel) {
|
|||||||
message.success(result)
|
message.success(result)
|
||||||
GetFollowList(currentGroupId.value).then(result => {
|
GetFollowList(currentGroupId.value).then(result => {
|
||||||
followList.value = result
|
followList.value = result
|
||||||
stocks.value = []
|
|
||||||
for (const followedStock of result) {
|
for (const followedStock of result) {
|
||||||
if (!stocks.value.includes(followedStock.StockCode)) {
|
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||||
stocks.value.push(followedStock.StockCode)
|
stocks.value.push(followedStock.StockCode)
|
||||||
@ -1339,7 +1313,6 @@ function SendMessage(result, type) {
|
|||||||
// SendDingDingMessage(msg,result["股票代码"])
|
// SendDingDingMessage(msg,result["股票代码"])
|
||||||
SendDingDingMessageByType(msg,result["股票代码"],type)
|
SendDingDingMessageByType(msg,result["股票代码"],type)
|
||||||
}
|
}
|
||||||
|
|
||||||
function aiReCheckStock(stock,stockCode) {
|
function aiReCheckStock(stock,stockCode) {
|
||||||
data.modelName=""
|
data.modelName=""
|
||||||
data.airesult=""
|
data.airesult=""
|
||||||
@ -1356,7 +1329,6 @@ function aiReCheckStock(stock, stockCode) {
|
|||||||
//message.info("sysPromptId:"+data.sysPromptId)
|
//message.info("sysPromptId:"+data.sysPromptId)
|
||||||
NewChatStream(stock,stockCode,data.question,data.sysPromptId)
|
NewChatStream(stock,stockCode,data.question,data.sysPromptId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function aiCheckStock(stock,stockCode){
|
function aiCheckStock(stock,stockCode){
|
||||||
GetAIResponseResult(stockCode).then(result => {
|
GetAIResponseResult(stockCode).then(result => {
|
||||||
if(result.content){
|
if(result.content){
|
||||||
@ -1394,7 +1366,8 @@ function aiCheckStock(stock, stockCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTypeName(type){
|
function getTypeName(type){
|
||||||
switch (type) {
|
switch (type)
|
||||||
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return "涨跌报警"
|
return "涨跌报警"
|
||||||
case 2:
|
case 2:
|
||||||
@ -1457,13 +1430,11 @@ async function copyToClipboard() {
|
|||||||
message.error('复制失败: ' + err);
|
message.error('复制失败: ' + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAsMarkdown(){
|
function saveAsMarkdown(){
|
||||||
SaveAsMarkdown(data.code,data.name).then(result => {
|
SaveAsMarkdown(data.code,data.name).then(result => {
|
||||||
message.success(result)
|
message.success(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAsMarkdown_old() {
|
function saveAsMarkdown_old() {
|
||||||
const blob = new Blob([data.airesult], { type: 'text/markdown;charset=utf-8' });
|
const blob = new Blob([data.airesult], { type: 'text/markdown;charset=utf-8' });
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
@ -1473,7 +1444,6 @@ function saveAsMarkdown_old() {
|
|||||||
URL.revokeObjectURL(link.href);
|
URL.revokeObjectURL(link.href);
|
||||||
link.remove()
|
link.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHtml(ref) {
|
function getHtml(ref) {
|
||||||
if (ref.value) {
|
if (ref.value) {
|
||||||
// 获取 MdPreview 组件的根元素
|
// 获取 MdPreview 组件的根元素
|
||||||
@ -1538,17 +1508,14 @@ function share(code, name) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addTabModel=ref({
|
const addTabModel=ref({
|
||||||
name: '',
|
name: '',
|
||||||
sort: 1,
|
sort: 1,
|
||||||
})
|
})
|
||||||
const addTabPane=ref(false)
|
const addTabPane=ref(false)
|
||||||
|
|
||||||
function addTab(){
|
function addTab(){
|
||||||
addTabPane.value=true
|
addTabPane.value=true
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveTabPane(){
|
function saveTabPane(){
|
||||||
AddGroup(addTabModel.value).then(result => {
|
AddGroup(addTabModel.value).then(result => {
|
||||||
message.info(result)
|
message.info(result)
|
||||||
@ -1558,7 +1525,6 @@ function saveTabPane() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddStockGroupInfo(groupId,code,name){
|
function AddStockGroupInfo(groupId,code,name){
|
||||||
if(code.startsWith("gb_")){
|
if(code.startsWith("gb_")){
|
||||||
code="us"+ code.replace("gb_", "").toLowerCase()
|
code="us"+ code.replace("gb_", "").toLowerCase()
|
||||||
@ -1571,11 +1537,11 @@ function AddStockGroupInfo(groupId, code, name) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTab(name){
|
function updateTab(name){
|
||||||
currentGroupId.value=Number(name)
|
currentGroupId.value=Number(name)
|
||||||
GetFollowList(currentGroupId.value).then(result => {
|
GetFollowList(currentGroupId.value).then(result => {
|
||||||
stocks.value=[]
|
stocks.value=[]
|
||||||
|
//console.log("GetFollowList",result)
|
||||||
followList.value = result
|
followList.value = result
|
||||||
for (const followedStock of result) {
|
for (const followedStock of result) {
|
||||||
if(followedStock.StockCode.startsWith("us")){
|
if(followedStock.StockCode.startsWith("us")){
|
||||||
@ -1588,7 +1554,6 @@ function updateTab(name) {
|
|||||||
message.destroyAll()
|
message.destroyAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function delTab(name){
|
function delTab(name){
|
||||||
let infos=groupList.value=groupList.value.filter(item => item.ID === Number(name))
|
let infos=groupList.value=groupList.value.filter(item => item.ID === Number(name))
|
||||||
dialog.create({
|
dialog.create({
|
||||||
@ -1607,65 +1572,35 @@ function delTab(name) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function delStockGroup(code,name,groupId){
|
function delStockGroup(code,name,groupId){
|
||||||
RemoveStockGroup(code,name,groupId).then(result => {
|
RemoveStockGroup(code,name,groupId).then(result => {
|
||||||
updateTab(groupId)
|
updateTab(groupId)
|
||||||
message.info(result)
|
message.info(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchNotice(stockCode) {
|
|
||||||
router.push({
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: '公司公告',
|
|
||||||
stockCode: stockCode,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchStockReport(stockCode) {
|
|
||||||
router.push({
|
|
||||||
name: 'market',
|
|
||||||
query: {
|
|
||||||
name: '个股研报',
|
|
||||||
stockCode: stockCode,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<vue-danmaku v-model:danmus="danmus" useSlot
|
<vue-danmaku v-model:danmus="danmus" useSlot style="height:100px; width:100%;z-index: 9;position:absolute; top: 400px; pointer-events: none;" >
|
||||||
style="height:100px; width:100%;z-index: 9;position:absolute; top: 400px; pointer-events: none;">
|
|
||||||
<template v-slot:dm="{ index, danmu }">
|
<template v-slot:dm="{ index, danmu }">
|
||||||
<n-gradient-text type="info">
|
<n-gradient-text type="info">
|
||||||
<n-icon :component="ChatboxOutline"/>
|
<n-icon :component="ChatboxOutline"/>{{ danmu }}
|
||||||
{{ danmu }}
|
|
||||||
</n-gradient-text>
|
</n-gradient-text>
|
||||||
</template>
|
</template>
|
||||||
</vue-danmaku>
|
</vue-danmaku>
|
||||||
<n-tabs type="card" style="--wails-draggable:drag" animated addable :data-currentGroupId="currentGroupId"
|
<n-tabs type="card" style="--wails-draggable:drag" animated addable :data-currentGroupId="currentGroupId" :value="currentGroupId" @add="addTab" @update-value="updateTab" placement="top" @close="(key)=>{delTab(key)}">
|
||||||
:value="currentGroupId" @add="addTab" @update-value="updateTab" placement="top" @close="(key)=>{delTab(key)}">
|
|
||||||
<n-tab-pane :name="0" :tab="'全部'">
|
<n-tab-pane :name="0" :tab="'全部'">
|
||||||
<n-grid :x-gap="8" :cols="3" :y-gap="8" >
|
<n-grid :x-gap="8" :cols="3" :y-gap="8" >
|
||||||
<n-gi :id="result['股票代码']+'_gi'" v-for="result in sortedResults" style="margin-left: 2px;" >
|
<n-gi :id="result['股票代码']+'_gi'" v-for="result in sortedResults" style="margin-left: 2px;" >
|
||||||
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true"
|
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true" :title="result['股票名称']" :closable="false" @close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||||
:title="result['股票名称']" :closable="false"
|
|
||||||
@close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
|
||||||
<n-grid :cols="1" :y-gap="6">
|
<n-grid :cols="1" :y-gap="6">
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<n-text :type="result.type" >
|
<n-text :type="result.type" >
|
||||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']"
|
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']" :to="Number(result['当前价格'])" />
|
||||||
:to="Number(result['当前价格'])"/>
|
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">({{result['盘前盘后']}} {{result['盘前盘后涨跌幅']}}%)</n-tag>
|
||||||
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">
|
|
||||||
({{ result['盘前盘后'] }} {{ result['盘前盘后涨跌幅'] }}%)
|
|
||||||
</n-tag>
|
|
||||||
</n-text>
|
</n-text>
|
||||||
<n-text style="padding-left: 10px;" :type="result.type">
|
<n-text style="padding-left: 10px;" :type="result.type">
|
||||||
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent"/>
|
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent" />%
|
||||||
%
|
|
||||||
</n-text>
|
</n-text>
|
||||||
<n-text size="small" v-if="result.costVolume>0" :type="result.type">
|
<n-text size="small" v-if="result.costVolume>0" :type="result.type">
|
||||||
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday" />
|
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday" />
|
||||||
@ -1735,51 +1670,31 @@ function searchStockReport(stockCode) {
|
|||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
|
|
||||||
<n-tag size="small" :bordered="false">{{result['股票代码']}}</n-tag>
|
<n-tag size="small" :bordered="false">{{result['股票代码']}}</n-tag>
|
||||||
<n-button size="tiny" secondary type="primary"
|
<n-button size="tiny" secondary type="primary" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||||
@click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
|
||||||
取消关注
|
取消关注
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning"
|
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning" @click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
||||||
@click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
|
||||||
AI分析
|
AI分析
|
||||||
</n-button>
|
</n-button>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-flex justify="center">
|
<n-flex justify="center">
|
||||||
<n-text :type="'info'">{{ result["日期"] + " " + result["时间"] }}</n-text>
|
|
||||||
<n-tag size="small" v-if="result.volume>0" :type="result.profitType">{{result.volume+"股"}}</n-tag>
|
<n-tag size="small" v-if="result.volume>0" :type="result.profitType">{{result.volume+"股"}}</n-tag>
|
||||||
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">
|
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">{{"成本:"+result.costPrice+"*"+result.costVolume+" "+result.profit+"%"+" ( "+result.profitAmount+" ¥ )"}}</n-tag>
|
||||||
{{ "成本:" + result.costPrice + "*" + result.costVolume + " " + result.profit + "%" + " ( " + result.profitAmount + " ¥ )" }}
|
|
||||||
</n-tag>
|
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
<template #action>
|
<template #action>
|
||||||
<n-flex justify="left">
|
<n-flex justify="space-between">
|
||||||
<n-button size="tiny" type="warning" @click="setStock(result['股票代码'],result['股票名称'])"> 成本
|
<n-text :type="'info'">{{result["日期"]+" "+result["时间"]}}</n-text>
|
||||||
</n-button>
|
<n-button size="tiny" type="info" @click="setStock(result['股票代码'],result['股票名称'])"> 成本 </n-button>
|
||||||
<n-button size="tiny" type="error"
|
<n-button size="tiny" type="success" @click="showFenshi(result['股票代码'],result['股票名称'])"> 分时 </n-button>
|
||||||
@click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时
|
|
||||||
</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="error" v-if="result['买一报价']>0"
|
<n-button size="tiny" type="warning" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
||||||
@click="showMoney(result['股票代码'],result['股票名称'])"> 资金
|
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name" @select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
||||||
</n-button>
|
<n-button type="success" size="tiny">设置分组</n-button>
|
||||||
<n-button size="tiny" type="success" @click="search(result['股票代码'],result['股票名称'])"> 详情
|
|
||||||
</n-button>
|
|
||||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
|
||||||
@click="searchNotice(result['股票代码'])"> 公告
|
|
||||||
</n-button>
|
|
||||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
|
||||||
@click="searchStockReport(result['股票代码'])"> 研报
|
|
||||||
</n-button>
|
|
||||||
<n-flex justify="right">
|
|
||||||
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name"
|
|
||||||
@select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
|
||||||
<n-button type="warning" size="tiny">设置分组</n-button>
|
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</n-flex>
|
|
||||||
</template>
|
</template>
|
||||||
</n-card >
|
</n-card >
|
||||||
</n-gi>
|
</n-gi>
|
||||||
@ -1788,21 +1703,15 @@ function searchStockReport(stockCode) {
|
|||||||
<n-tab-pane closable v-for="group in groupList" :group-id="group.ID" :name="group.ID" :tab="group.name">
|
<n-tab-pane closable v-for="group in groupList" :group-id="group.ID" :name="group.ID" :tab="group.name">
|
||||||
<n-grid :x-gap="8" :cols="3" :y-gap="8" >
|
<n-grid :x-gap="8" :cols="3" :y-gap="8" >
|
||||||
<n-gi :id="result['股票代码']+'_gi'" v-for="result in groupResults" style="margin-left: 2px;" >
|
<n-gi :id="result['股票代码']+'_gi'" v-for="result in groupResults" style="margin-left: 2px;" >
|
||||||
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true"
|
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true" :title="result['股票名称']" :closable="false" @close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||||
:title="result['股票名称']" :closable="false"
|
|
||||||
@close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
|
||||||
<n-grid :cols="1" :y-gap="6">
|
<n-grid :cols="1" :y-gap="6">
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<n-text :type="result.type" >
|
<n-text :type="result.type" >
|
||||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']"
|
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']" :to="Number(result['当前价格'])" />
|
||||||
:to="Number(result['当前价格'])"/>
|
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">({{result['盘前盘后']}} {{result['盘前盘后涨跌幅']}}%)</n-tag>
|
||||||
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">
|
|
||||||
({{ result['盘前盘后'] }} {{ result['盘前盘后涨跌幅'] }}%)
|
|
||||||
</n-tag>
|
|
||||||
</n-text>
|
</n-text>
|
||||||
<n-text style="padding-left: 10px;" :type="result.type">
|
<n-text style="padding-left: 10px;" :type="result.type">
|
||||||
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent"/>
|
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent" />%
|
||||||
%
|
|
||||||
</n-text>
|
</n-text>
|
||||||
<n-text size="small" v-if="result.costVolume>0" :type="result.type">
|
<n-text size="small" v-if="result.costVolume>0" :type="result.type">
|
||||||
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday" />
|
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday" />
|
||||||
@ -1872,52 +1781,31 @@ function searchStockReport(stockCode) {
|
|||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
|
|
||||||
<n-tag size="small" :bordered="false">{{result['股票代码']}}</n-tag>
|
<n-tag size="small" :bordered="false">{{result['股票代码']}}</n-tag>
|
||||||
<n-button size="tiny" secondary type="primary"
|
<n-button size="tiny" secondary type="primary" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||||
@click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
|
||||||
取消关注
|
取消关注
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning"
|
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning" @click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
||||||
@click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
|
||||||
AI分析
|
AI分析
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button secondary type="error" size="tiny"
|
<n-button secondary type="error" size="tiny" @click="delStockGroup(result['股票代码'],result['股票名称'],group.ID)">移出分组</n-button>
|
||||||
@click="delStockGroup(result['股票代码'],result['股票名称'],group.ID)">移出分组
|
|
||||||
</n-button>
|
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-flex justify="center">
|
<n-flex justify="center">
|
||||||
<n-text :type="'info'">{{ result["日期"] + " " + result["时间"] }}</n-text>
|
|
||||||
<n-tag size="small" v-if="result.volume>0" :type="result.profitType">{{result.volume+"股"}}</n-tag>
|
<n-tag size="small" v-if="result.volume>0" :type="result.profitType">{{result.volume+"股"}}</n-tag>
|
||||||
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">
|
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">{{"成本:"+result.costPrice+"*"+result.costVolume+" "+result.profit+"%"+" ( "+result.profitAmount+" ¥ )"}}</n-tag>
|
||||||
{{ "成本:" + result.costPrice + "*" + result.costVolume + " " + result.profit + "%" + " ( " + result.profitAmount + " ¥ )" }}
|
|
||||||
</n-tag>
|
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
<template #action>
|
<template #action>
|
||||||
<n-flex justify="left">
|
<n-flex justify="space-between">
|
||||||
<n-button size="tiny" type="warning" @click="setStock(result['股票代码'],result['股票名称'])"> 成本
|
<n-text :type="'info'">{{result["日期"]+" "+result["时间"]}}</n-text>
|
||||||
</n-button>
|
<n-button size="tiny" type="info" @click="setStock(result['股票代码'],result['股票名称'])"> 成本 </n-button>
|
||||||
<n-button size="tiny" type="error"
|
<n-button size="tiny" type="success" @click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时 </n-button>
|
||||||
@click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时
|
|
||||||
</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="error" v-if="result['买一报价']>0"
|
<n-button size="tiny" type="warning" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
||||||
@click="showMoney(result['股票代码'],result['股票名称'])"> 资金
|
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name" @select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
||||||
</n-button>
|
<n-button type="success" size="tiny">设置分组</n-button>
|
||||||
<n-button size="tiny" type="success" @click="search(result['股票代码'],result['股票名称'])"> 详情
|
|
||||||
</n-button>
|
|
||||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
|
||||||
@click="searchNotice(result['股票代码'])"> 公告
|
|
||||||
</n-button>
|
|
||||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
|
||||||
@click="searchStockReport(result['股票代码'])"> 研报
|
|
||||||
</n-button>
|
|
||||||
<n-flex justify="right">
|
|
||||||
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name"
|
|
||||||
@select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
|
||||||
<n-button type="warning" size="tiny">设置分组</n-button>
|
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
</n-flex>
|
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
</n-card >
|
</n-card >
|
||||||
@ -1937,24 +1825,16 @@ function searchStockReport(stockCode) {
|
|||||||
:options="options"
|
:options="options"
|
||||||
placeholder="股票指数名称/代码/弹幕"
|
placeholder="股票指数名称/代码/弹幕"
|
||||||
clearable @update-value="getStockList" :on-select="onSelect"/>
|
clearable @update-value="getStockList" :on-select="onSelect"/>
|
||||||
|
|
||||||
<n-popover trigger="manual" :show="showPopover">
|
|
||||||
<template #trigger>
|
|
||||||
<n-button type="primary" @click="AddStock" v-if="addBTN">
|
<n-button type="primary" @click="AddStock" v-if="addBTN">
|
||||||
<n-icon :component="Add"/> 关注
|
<n-icon :component="Add"/> 关注
|
||||||
</n-button>
|
</n-button>
|
||||||
</template>
|
|
||||||
<span>输入股票名称/代码关键词开始吧~~~</span>
|
|
||||||
</n-popover>
|
|
||||||
|
|
||||||
<n-button type="info" @click="SendDanmu" v-if="data.enableDanmu">
|
<n-button type="info" @click="SendDanmu" v-if="data.enableDanmu">
|
||||||
<n-icon :component="ChatboxOutline"/> 发送弹幕
|
<n-icon :component="ChatboxOutline"/> 发送弹幕
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
<!-- </n-card>-->
|
<!-- </n-card>-->
|
||||||
</div>
|
</div>
|
||||||
<n-modal transform-origin="center" size="small" v-model:show="modalShow" :title="formModel.name" style="width: 400px"
|
<n-modal transform-origin="center" size="small" v-model:show="modalShow" :title="formModel.name" style="width: 400px" :preset="'card'">
|
||||||
:preset="'card'">
|
|
||||||
<n-form :model="formModel" :rules="{
|
<n-form :model="formModel" :rules="{
|
||||||
costPrice: { required: true, message: '请输入成本'},
|
costPrice: { required: true, message: '请输入成本'},
|
||||||
volume: { required: true, message: '请输入数量'},
|
volume: { required: true, message: '请输入数量'},
|
||||||
@ -1999,10 +1879,7 @@ function searchStockReport(stockCode) {
|
|||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-button type="primary"
|
<n-button type="primary" @click="updateCostPriceAndVolumeNew(formModel.code,formModel.costPrice,formModel.volume,formModel.alarm,formModel)">保存</n-button>
|
||||||
@click="updateCostPriceAndVolumeNew(formModel.code,formModel.costPrice,formModel.volume,formModel.alarm,formModel)">
|
|
||||||
保存
|
|
||||||
</n-button>
|
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
|
||||||
@ -2011,14 +1888,12 @@ function searchStockReport(stockCode) {
|
|||||||
:model="addTabModel"
|
:model="addTabModel"
|
||||||
size="medium"
|
size="medium"
|
||||||
label-placement="left"
|
label-placement="left"
|
||||||
>
|
> <n-grid :cols="2" >
|
||||||
<n-grid :cols="2">
|
|
||||||
<n-form-item-gi label="分组名称:" path="name" :span="5">
|
<n-form-item-gi label="分组名称:" path="name" :span="5">
|
||||||
<n-input v-model:value="addTabModel.name" style="width: 100%" placeholder="请输入分组名称" />
|
<n-input v-model:value="addTabModel.name" style="width: 100%" placeholder="请输入分组名称" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi label="分组排序:" path="sort" :span="5">
|
<n-form-item-gi label="分组排序:" path="sort" :span="5">
|
||||||
<n-input-number v-model:value="addTabModel.sort" style="width: 100%" min="0"
|
<n-input-number v-model:value="addTabModel.sort" style="width: 100%" min="0" placeholder="请输入分组排序值" ></n-input-number>
|
||||||
placeholder="请输入分组排序值"></n-input-number>
|
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
</n-form>
|
</n-form>
|
||||||
@ -2033,36 +1908,28 @@ function searchStockReport(stockCode) {
|
|||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
<n-modal v-model:show="modalShow2" :title="data.name+' '+ data.changePercent+'%'" style="width: 1000px"
|
<n-modal v-model:show="modalShow2" :title="data.name" style="width: 1000px" :preset="'card'" @after-enter="handleFeishi" @after-leave="clearFeishi">
|
||||||
:preset="'card'" @after-enter="handleFeishi" @after-leave="clearFeishi">
|
|
||||||
<!-- <n-image :src="data.fenshiURL" />-->
|
<!-- <n-image :src="data.fenshiURL" />-->
|
||||||
<div ref="kLineChartRef2" style="width: 1000px; height: 500px;"></div>
|
<div ref="kLineChartRef2" style="width: 1000px; height: 500px;"></div>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
<n-modal v-model:show="modalShow3" :title="data.name" style="width: 1000px" :preset="'card'"
|
<n-modal v-model:show="modalShow3" :title="data.name" style="width: 1000px" :preset="'card'" @after-enter="handleKLine">
|
||||||
@after-enter="handleKLine">
|
|
||||||
<!-- <n-image :src="data.kURL" />-->
|
<!-- <n-image :src="data.kURL" />-->
|
||||||
<div ref="kLineChartRef" style="width: 1000px; height: 500px;"></div>
|
<div ref="kLineChartRef" style="width: 1000px; height: 500px;"></div>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
|
||||||
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;"
|
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;" :title="'['+data.name+']AI分析结果'" >
|
||||||
:title="'['+data.name+']AI分析结果'">
|
|
||||||
<n-spin size="small" :show="data.loading">
|
<n-spin size="small" :show="data.loading">
|
||||||
<MdEditor v-if="enableEditor" :toolbars="toolbars" ref="mdEditorRef" style="height: 440px;text-align: left"
|
<MdEditor v-if="enableEditor" :toolbars="toolbars" ref="mdEditorRef" style="height: 440px;text-align: left" :modelValue="data.airesult" :theme="theme">
|
||||||
:modelValue="data.airesult" :theme="theme">
|
|
||||||
<template #defToolbars>
|
<template #defToolbars>
|
||||||
<ExportPDF :file-name="data.name+'['+data.code+']AI分析报告'" style="text-align: left"
|
<ExportPDF :file-name="data.name+'['+data.code+']AI分析报告'" style="text-align: left" :modelValue="data.airesult" @onProgress="handleProgress" />
|
||||||
:modelValue="data.airesult" @onProgress="handleProgress"/>
|
|
||||||
</template>
|
</template>
|
||||||
</MdEditor >
|
</MdEditor >
|
||||||
<MdPreview v-if="!enableEditor" ref="mdPreviewRef" style="height: 440px;text-align: left"
|
<MdPreview v-if="!enableEditor" ref="mdPreviewRef" style="height: 440px;text-align: left" :modelValue="data.airesult" :theme="theme"/>
|
||||||
:modelValue="data.airesult" :theme="theme"/>
|
|
||||||
</n-spin>
|
</n-spin>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-flex justify="space-between" ref="tipsRef">
|
<n-flex justify="space-between" ref="tipsRef">
|
||||||
<n-text type="info" v-if="data.time" >
|
<n-text type="info" v-if="data.time" >
|
||||||
<n-tag v-if="data.modelName" type="warning" round :title="data.chatId" :bordered="false">
|
<n-tag v-if="data.modelName" type="warning" round :title="data.chatId" :bordered="false">{{data.modelName}}</n-tag>
|
||||||
{{ data.modelName }}
|
|
||||||
</n-tag>
|
|
||||||
{{data.time}}
|
{{data.time}}
|
||||||
</n-text>
|
</n-text>
|
||||||
<n-text type="error" >*AI分析结果仅供参考,请以实际行情为准。投资需谨慎,风险自担。</n-text>
|
<n-text type="error" >*AI分析结果仅供参考,请以实际行情为准。投资需谨慎,风险自担。</n-text>
|
||||||
@ -2071,10 +1938,8 @@ function searchStockReport(stockCode) {
|
|||||||
<template #action>
|
<template #action>
|
||||||
|
|
||||||
<n-flex justify="space-between" style="margin-bottom: 10px">
|
<n-flex justify="space-between" style="margin-bottom: 10px">
|
||||||
<n-select style="width: 49%" v-model:value="data.sysPromptId" label-field="name" value-field="ID"
|
<n-select style="width: 49%" v-model:value="data.sysPromptId" label-field="name" value-field="ID" :options="sysPromptOptions" placeholder="请选择系统提示词" />
|
||||||
:options="sysPromptOptions" placeholder="请选择系统提示词"/>
|
<n-select style="width: 49%" v-model:value="data.question" label-field="name" value-field="content" :options="userPromptOptions" placeholder="请选择用户提示词" />
|
||||||
<n-select style="width: 49%" v-model:value="data.question" label-field="name" value-field="content"
|
|
||||||
:options="userPromptOptions" placeholder="请选择用户提示词"/>
|
|
||||||
</n-flex>
|
</n-flex>
|
||||||
<n-flex justify="right">
|
<n-flex justify="right">
|
||||||
<n-input v-model:value="data.question" style="text-align: left" clearable
|
<n-input v-model:value="data.question" style="text-align: left" clearable
|
||||||
@ -2096,10 +1961,6 @@ function searchStockReport(stockCode) {
|
|||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
<n-modal v-model:show="modalShow5" :title="data.name+'资金趋势'" style="width: 1000px" :preset="'card'">
|
|
||||||
<money-trend :code="data.code" :name="data.name" :days="360" :dark-theme="data.darkTheme"
|
|
||||||
:chart-height="500"></money-trend>
|
|
||||||
</n-modal>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@ -2110,7 +1971,6 @@ function searchStockReport(stockCode) {
|
|||||||
.md-editor-preview p{
|
.md-editor-preview p{
|
||||||
text-align: left !important;
|
text-align: left !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 添加闪烁效果的CSS类 */
|
/* 添加闪烁效果的CSS类 */
|
||||||
.blink-border {
|
.blink-border {
|
||||||
animation: blink-border 1s linear infinite;
|
animation: blink-border 1s linear infinite;
|
||||||
|
@ -12,7 +12,6 @@ const routes = [
|
|||||||
{ path: '/settings', component: settingsView,name: 'settings' },
|
{ path: '/settings', component: settingsView,name: 'settings' },
|
||||||
{ path: '/about', component: about,name: 'about' },
|
{ path: '/about', component: about,name: 'about' },
|
||||||
{ path: '/market', component: market,name: 'market' },
|
{ path: '/market', component: market,name: 'market' },
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
30
frontend/wailsjs/go/main/App.d.ts
vendored
30
frontend/wailsjs/go/main/App.d.ts
vendored
@ -11,16 +11,10 @@ export function AddPrompt(arg1:models.Prompt):Promise<string>;
|
|||||||
|
|
||||||
export function AddStockGroup(arg1:number,arg2:string):Promise<string>;
|
export function AddStockGroup(arg1:number,arg2:string):Promise<string>;
|
||||||
|
|
||||||
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 ExportConfig():Promise<string>;
|
export function ExportConfig():Promise<string>;
|
||||||
|
|
||||||
export function Follow(arg1:string):Promise<string>;
|
export function Follow(arg1:string):Promise<string>;
|
||||||
@ -39,7 +33,7 @@ export function GetGroupList():Promise<Array<data.Group>>;
|
|||||||
|
|
||||||
export function GetGroupStockList(arg1:number):Promise<Array<data.GroupStock>>;
|
export function GetGroupStockList(arg1:number):Promise<Array<data.GroupStock>>;
|
||||||
|
|
||||||
export function GetIndustryMoneyRankSina(arg1:string,arg2:string):Promise<Array<Record<string, any>>>;
|
export function GetIndustryMoneyRankSina(arg1:string):Promise<Array<Record<string, any>>>;
|
||||||
|
|
||||||
export function GetIndustryRank(arg1:string,arg2:number):Promise<Array<any>>;
|
export function GetIndustryRank(arg1:string,arg2:number):Promise<Array<any>>;
|
||||||
|
|
||||||
@ -55,8 +49,6 @@ export function GetStockList(arg1:string):Promise<Array<data.StockBasic>>;
|
|||||||
|
|
||||||
export function GetStockMinutePriceLineData(arg1:string,arg2:string):Promise<Record<string, any>>;
|
export function GetStockMinutePriceLineData(arg1:string,arg2:string):Promise<Record<string, any>>;
|
||||||
|
|
||||||
export function GetStockMoneyTrendByDay(arg1:string,arg2:number):Promise<Array<Record<string, any>>>;
|
|
||||||
|
|
||||||
export function GetTelegraphList(arg1:string):Promise<any>;
|
export function GetTelegraphList(arg1:string):Promise<any>;
|
||||||
|
|
||||||
export function GetVersionInfo():Promise<models.VersionInfo>;
|
export function GetVersionInfo():Promise<models.VersionInfo>;
|
||||||
@ -67,22 +59,8 @@ export function GlobalStockIndexes():Promise<Record<string, any>>;
|
|||||||
|
|
||||||
export function Greet(arg1:string):Promise<data.StockInfo>;
|
export function Greet(arg1:string):Promise<data.StockInfo>;
|
||||||
|
|
||||||
export function HotEvent(arg1:number):Promise<any>;
|
|
||||||
|
|
||||||
export function HotStock(arg1:string):Promise<any>;
|
|
||||||
|
|
||||||
export function HotTopic(arg1:number):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 NewChatStream(arg1:string,arg2:string,arg3:string,arg4:any):Promise<void>;
|
export function NewChatStream(arg1:string,arg2:string,arg3:string,arg4:any):Promise<void>;
|
||||||
|
|
||||||
export function NewsPush(arg1:any):Promise<void>;
|
|
||||||
|
|
||||||
export function ReFleshTelegraphList(arg1:string):Promise<any>;
|
export function ReFleshTelegraphList(arg1:string):Promise<any>;
|
||||||
|
|
||||||
export function RemoveGroup(arg1:number):Promise<string>;
|
export function RemoveGroup(arg1:number):Promise<string>;
|
||||||
@ -93,8 +71,6 @@ 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>;
|
||||||
@ -109,10 +85,6 @@ export function SetStockSort(arg1:number,arg2:string):Promise<void>;
|
|||||||
|
|
||||||
export function ShareAnalysis(arg1:string,arg2:string):Promise<string>;
|
export function ShareAnalysis(arg1:string,arg2:string):Promise<string>;
|
||||||
|
|
||||||
export function StockNotice(arg1:string):Promise<Array<any>>;
|
|
||||||
|
|
||||||
export function StockResearchReport(arg1:string):Promise<Array<any>>;
|
|
||||||
|
|
||||||
export function SummaryStockNews(arg1:string,arg2:any):Promise<void>;
|
export function SummaryStockNews(arg1:string,arg2:any):Promise<void>;
|
||||||
|
|
||||||
export function UnFollow(arg1:string):Promise<string>;
|
export function UnFollow(arg1:string):Promise<string>;
|
||||||
|
@ -18,26 +18,14 @@ export function AddStockGroup(arg1, arg2) {
|
|||||||
return window['go']['main']['App']['AddStockGroup'](arg1, arg2);
|
return window['go']['main']['App']['AddStockGroup'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AnalyzeSentiment(arg1) {
|
|
||||||
return window['go']['main']['App']['AnalyzeSentiment'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function CheckUpdate() {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EMDictCode(arg1) {
|
|
||||||
return window['go']['main']['App']['EMDictCode'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ExportConfig() {
|
export function ExportConfig() {
|
||||||
return window['go']['main']['App']['ExportConfig']();
|
return window['go']['main']['App']['ExportConfig']();
|
||||||
}
|
}
|
||||||
@ -74,8 +62,8 @@ export function GetGroupStockList(arg1) {
|
|||||||
return window['go']['main']['App']['GetGroupStockList'](arg1);
|
return window['go']['main']['App']['GetGroupStockList'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetIndustryMoneyRankSina(arg1, arg2) {
|
export function GetIndustryMoneyRankSina(arg1) {
|
||||||
return window['go']['main']['App']['GetIndustryMoneyRankSina'](arg1, arg2);
|
return window['go']['main']['App']['GetIndustryMoneyRankSina'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetIndustryRank(arg1, arg2) {
|
export function GetIndustryRank(arg1, arg2) {
|
||||||
@ -106,10 +94,6 @@ export function GetStockMinutePriceLineData(arg1, arg2) {
|
|||||||
return window['go']['main']['App']['GetStockMinutePriceLineData'](arg1, arg2);
|
return window['go']['main']['App']['GetStockMinutePriceLineData'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetStockMoneyTrendByDay(arg1, arg2) {
|
|
||||||
return window['go']['main']['App']['GetStockMoneyTrendByDay'](arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function GetTelegraphList(arg1) {
|
export function GetTelegraphList(arg1) {
|
||||||
return window['go']['main']['App']['GetTelegraphList'](arg1);
|
return window['go']['main']['App']['GetTelegraphList'](arg1);
|
||||||
}
|
}
|
||||||
@ -130,38 +114,10 @@ export function Greet(arg1) {
|
|||||||
return window['go']['main']['App']['Greet'](arg1);
|
return window['go']['main']['App']['Greet'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HotEvent(arg1) {
|
|
||||||
return window['go']['main']['App']['HotEvent'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HotStock(arg1) {
|
|
||||||
return window['go']['main']['App']['HotStock'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HotTopic(arg1) {
|
|
||||||
return window['go']['main']['App']['HotTopic'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function IndustryResearchReport(arg1) {
|
|
||||||
return window['go']['main']['App']['IndustryResearchReport'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InvestCalendarTimeLine(arg1) {
|
|
||||||
return window['go']['main']['App']['InvestCalendarTimeLine'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function LongTigerRank(arg1) {
|
|
||||||
return window['go']['main']['App']['LongTigerRank'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NewChatStream(arg1, arg2, arg3, arg4) {
|
export function NewChatStream(arg1, arg2, arg3, arg4) {
|
||||||
return window['go']['main']['App']['NewChatStream'](arg1, arg2, arg3, arg4);
|
return window['go']['main']['App']['NewChatStream'](arg1, arg2, arg3, arg4);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NewsPush(arg1) {
|
|
||||||
return window['go']['main']['App']['NewsPush'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ReFleshTelegraphList(arg1) {
|
export function ReFleshTelegraphList(arg1) {
|
||||||
return window['go']['main']['App']['ReFleshTelegraphList'](arg1);
|
return window['go']['main']['App']['ReFleshTelegraphList'](arg1);
|
||||||
}
|
}
|
||||||
@ -182,10 +138,6 @@ 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);
|
||||||
}
|
}
|
||||||
@ -214,14 +166,6 @@ export function ShareAnalysis(arg1, arg2) {
|
|||||||
return window['go']['main']['App']['ShareAnalysis'](arg1, arg2);
|
return window['go']['main']['App']['ShareAnalysis'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StockNotice(arg1) {
|
|
||||||
return window['go']['main']['App']['StockNotice'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StockResearchReport(arg1) {
|
|
||||||
return window['go']['main']['App']['StockResearchReport'](arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SummaryStockNews(arg1, arg2) {
|
export function SummaryStockNews(arg1, arg2) {
|
||||||
return window['go']['main']['App']['SummaryStockNews'](arg1, arg2);
|
return window['go']['main']['App']['SummaryStockNews'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
@ -290,26 +290,6 @@ export namespace data {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class SentimentResult {
|
|
||||||
Score: number;
|
|
||||||
Category: number;
|
|
||||||
PositiveCount: number;
|
|
||||||
NegativeCount: number;
|
|
||||||
Description: string;
|
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
|
||||||
return new SentimentResult(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
|
||||||
if ('string' === typeof source) source = JSON.parse(source);
|
|
||||||
this.Score = source["Score"];
|
|
||||||
this.Category = source["Category"];
|
|
||||||
this.PositiveCount = source["PositiveCount"];
|
|
||||||
this.NegativeCount = source["NegativeCount"];
|
|
||||||
this.Description = source["Description"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class Settings {
|
export class Settings {
|
||||||
ID: number;
|
ID: number;
|
||||||
// Go type: time
|
// Go type: time
|
||||||
@ -342,7 +322,6 @@ export namespace data {
|
|||||||
darkTheme: boolean;
|
darkTheme: boolean;
|
||||||
browserPoolSize: number;
|
browserPoolSize: number;
|
||||||
enableFund: boolean;
|
enableFund: boolean;
|
||||||
enablePushNews: boolean;
|
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
static createFrom(source: any = {}) {
|
||||||
return new Settings(source);
|
return new Settings(source);
|
||||||
@ -378,7 +357,6 @@ export namespace data {
|
|||||||
this.darkTheme = source["darkTheme"];
|
this.darkTheme = source["darkTheme"];
|
||||||
this.browserPoolSize = source["browserPoolSize"];
|
this.browserPoolSize = source["browserPoolSize"];
|
||||||
this.enableFund = source["enableFund"];
|
this.enableFund = source["enableFund"];
|
||||||
this.enablePushNews = source["enablePushNews"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||||
|
17
go.mod
17
go.mod
@ -1,6 +1,8 @@
|
|||||||
module go-stock
|
module go-stock
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23
|
||||||
|
|
||||||
|
toolchain go1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PuerkitoBio/goquery v1.10.1
|
github.com/PuerkitoBio/goquery v1.10.1
|
||||||
@ -9,18 +11,16 @@ require (
|
|||||||
github.com/duke-git/lancet/v2 v2.3.4
|
github.com/duke-git/lancet/v2 v2.3.4
|
||||||
github.com/energye/systray v1.0.2
|
github.com/energye/systray v1.0.2
|
||||||
github.com/glebarez/sqlite v1.11.0
|
github.com/glebarez/sqlite v1.11.0
|
||||||
github.com/go-ego/gse v0.80.3
|
|
||||||
github.com/go-resty/resty/v2 v2.16.2
|
github.com/go-resty/resty/v2 v2.16.2
|
||||||
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
|
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
|
||||||
github.com/robertkrimen/otto v0.5.1
|
github.com/robertkrimen/otto v0.5.1
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/samber/lo v1.49.1
|
github.com/samber/lo v1.49.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/tidwall/gjson v1.14.2
|
|
||||||
github.com/wailsapp/wails/v2 v2.10.1
|
github.com/wailsapp/wails/v2 v2.10.1
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/sys v0.31.0
|
golang.org/x/sys v0.30.0
|
||||||
golang.org/x/text v0.23.0
|
golang.org/x/text v0.22.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
gorm.io/gorm v1.25.12
|
gorm.io/gorm v1.25.12
|
||||||
gorm.io/plugin/dbresolver v1.5.3
|
gorm.io/plugin/dbresolver v1.5.3
|
||||||
@ -62,18 +62,15 @@ require (
|
|||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/tevino/abool v0.0.0-20220530134649-2bfc934cb23c // indirect
|
github.com/tevino/abool v0.0.0-20220530134649-2bfc934cb23c // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
|
||||||
github.com/tkrajina/go-reflector v0.5.8 // indirect
|
github.com/tkrajina/go-reflector v0.5.8 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
github.com/vcaesar/cedar v0.20.2 // indirect
|
|
||||||
github.com/wailsapp/go-webview2 v1.0.19 // indirect
|
github.com/wailsapp/go-webview2 v1.0.19 // indirect
|
||||||
github.com/wailsapp/mimetype v1.4.1 // indirect
|
github.com/wailsapp/mimetype v1.4.1 // indirect
|
||||||
go.uber.org/multierr v1.10.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.33.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||||
golang.org/x/net v0.38.0 // indirect
|
golang.org/x/net v0.35.0 // indirect
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
modernc.org/libc v1.22.5 // indirect
|
modernc.org/libc v1.22.5 // indirect
|
||||||
|
28
go.sum
28
go.sum
@ -26,8 +26,6 @@ github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9g
|
|||||||
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=
|
||||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||||
github.com/go-ego/gse v0.80.3 h1:YNFkjMhlhQnUeuoFcUEd1ivh6SOB764rT8GDsEbDiEg=
|
|
||||||
github.com/go-ego/gse v0.80.3/go.mod h1:Gt3A9Ry1Eso2Kza4MRaiZ7f2DTAvActmETY46Lxg0gU=
|
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg=
|
github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg=
|
||||||
@ -119,22 +117,12 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
|||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tevino/abool v0.0.0-20220530134649-2bfc934cb23c h1:coVla7zpsycc+kA9NXpcvv2E4I7+ii6L5hZO2S6C3kw=
|
github.com/tevino/abool v0.0.0-20220530134649-2bfc934cb23c h1:coVla7zpsycc+kA9NXpcvv2E4I7+ii6L5hZO2S6C3kw=
|
||||||
github.com/tevino/abool v0.0.0-20220530134649-2bfc934cb23c/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg=
|
github.com/tevino/abool v0.0.0-20220530134649-2bfc934cb23c/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg=
|
||||||
github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo=
|
|
||||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
|
||||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
|
||||||
github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ=
|
github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ=
|
||||||
github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/vcaesar/cedar v0.20.2 h1:TDx7AdZhilKcfE1WvdToTJf5VrC/FXcUOW+KY1upLZ4=
|
|
||||||
github.com/vcaesar/cedar v0.20.2/go.mod h1:lyuGvALuZZDPNXwpzv/9LyxW+8Y6faN7zauFezNsnik=
|
|
||||||
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
|
|
||||||
github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU=
|
|
||||||
github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU=
|
github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU=
|
||||||
github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||||
@ -154,8 +142,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
|||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@ -173,8 +161,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -199,8 +187,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@ -220,8 +208,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||||
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
101
main.go
101
main.go
@ -1,11 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"embed"
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/slice"
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
"github.com/wailsapp/wails/v2"
|
"github.com/wailsapp/wails/v2"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
@ -21,7 +20,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,6 +62,21 @@ func main() {
|
|||||||
// Sort: 0,
|
// Sort: 0,
|
||||||
//})
|
//})
|
||||||
|
|
||||||
|
if stocksBin != nil && len(stocksBin) > 0 {
|
||||||
|
go initStockData()
|
||||||
|
}
|
||||||
|
log.SugaredLogger.Infof("init stocksBinHK %d", len(stocksBinHK))
|
||||||
|
|
||||||
|
if stocksBinHK != nil && len(stocksBinHK) > 0 {
|
||||||
|
go initStockDataHK()
|
||||||
|
}
|
||||||
|
log.SugaredLogger.Infof("init stocksBinUS %d", len(stocksBinUS))
|
||||||
|
|
||||||
|
if stocksBinUS != nil && len(stocksBinUS) > 0 {
|
||||||
|
go initStockDataUS()
|
||||||
|
}
|
||||||
|
updateBasicInfo()
|
||||||
|
|
||||||
// Create an instance of the app structure
|
// Create an instance of the app structure
|
||||||
app := NewApp()
|
app := NewApp()
|
||||||
AppMenu := menu.NewMenu()
|
AppMenu := menu.NewMenu()
|
||||||
@ -203,13 +216,9 @@ func AutoMigrate() {
|
|||||||
db.Dao.AutoMigrate(&models.Tags{})
|
db.Dao.AutoMigrate(&models.Tags{})
|
||||||
db.Dao.AutoMigrate(&models.Telegraph{})
|
db.Dao.AutoMigrate(&models.Telegraph{})
|
||||||
db.Dao.AutoMigrate(&models.TelegraphTags{})
|
db.Dao.AutoMigrate(&models.TelegraphTags{})
|
||||||
db.Dao.AutoMigrate(&models.LongTigerRankData{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initStockDataUS(ctx context.Context) {
|
func initStockDataUS() {
|
||||||
defer func() {
|
|
||||||
go runtime.EventsEmit(ctx, "loadingMsg", "done")
|
|
||||||
}()
|
|
||||||
var v []models.StockInfoUS
|
var v []models.StockInfoUS
|
||||||
err := json.Unmarshal(stocksBinUS, &v)
|
err := json.Unmarshal(stocksBinUS, &v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -232,10 +241,7 @@ func initStockDataUS(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initStockDataHK(ctx context.Context) {
|
func initStockDataHK() {
|
||||||
defer func() {
|
|
||||||
go runtime.EventsEmit(ctx, "loadingMsg", "done")
|
|
||||||
}()
|
|
||||||
var v []models.StockInfoHK
|
var v []models.StockInfoHK
|
||||||
err := json.Unmarshal(stocksBinHK, &v)
|
err := json.Unmarshal(stocksBinHK, &v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -268,11 +274,7 @@ func updateBasicInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initStockData(ctx context.Context) {
|
func initStockData() {
|
||||||
defer func() {
|
|
||||||
go runtime.EventsEmit(ctx, "loadingMsg", "done")
|
|
||||||
}()
|
|
||||||
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"
|
|
||||||
log.SugaredLogger.Info("init stock data")
|
log.SugaredLogger.Info("init stock data")
|
||||||
res := &data.TushareStockBasicResponse{}
|
res := &data.TushareStockBasicResponse{}
|
||||||
err := json.Unmarshal(stocksBin, res)
|
err := json.Unmarshal(stocksBin, res)
|
||||||
@ -280,24 +282,26 @@ func initStockData(ctx context.Context) {
|
|||||||
log.SugaredLogger.Error(err.Error())
|
log.SugaredLogger.Error(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range res.Data.Items {
|
for _, item := range res.Data.Items {
|
||||||
stock := &data.StockBasic{}
|
stock := &data.StockBasic{}
|
||||||
stockData := map[string]any{}
|
stock.Exchange = convertor.ToString(item[0])
|
||||||
for _, field := range strings.Split(fields, ",") {
|
stock.IsHs = convertor.ToString(item[1])
|
||||||
//logger.SugaredLogger.Infof("field: %s", field)
|
stock.Name = convertor.ToString(item[2])
|
||||||
idx := slice.IndexOf(res.Data.Fields, field)
|
stock.Industry = convertor.ToString(item[3])
|
||||||
if idx == -1 {
|
stock.ListStatus = convertor.ToString(item[4])
|
||||||
continue
|
stock.ActName = convertor.ToString(item[5])
|
||||||
}
|
stock.ID = uint(item[6].(float64))
|
||||||
stockData[field] = item[idx]
|
stock.CurrType = convertor.ToString(item[7])
|
||||||
}
|
stock.Area = convertor.ToString(item[8])
|
||||||
jsonData, _ := json.Marshal(stockData)
|
stock.ListDate = convertor.ToString(item[9])
|
||||||
err := json.Unmarshal(jsonData, stock)
|
stock.DelistDate = convertor.ToString(item[10])
|
||||||
if err != nil {
|
stock.ActEntType = convertor.ToString(item[11])
|
||||||
continue
|
stock.TsCode = convertor.ToString(item[12])
|
||||||
}
|
stock.Symbol = convertor.ToString(item[13])
|
||||||
stock.ID = 0
|
stock.Cnspell = convertor.ToString(item[14])
|
||||||
|
stock.Fullname = convertor.ToString(item[20])
|
||||||
|
stock.Ename = convertor.ToString(item[21])
|
||||||
|
|
||||||
var count int64
|
var count int64
|
||||||
db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).Count(&count)
|
db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).Count(&count)
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
@ -305,38 +309,7 @@ func initStockData(ctx context.Context) {
|
|||||||
} else {
|
} else {
|
||||||
db.Dao.Create(stock)
|
db.Dao.Create(stock)
|
||||||
}
|
}
|
||||||
|
|
||||||
//db.Dao.Model(&data.StockBasic{}).FirstOrCreate(stock, &data.StockBasic{TsCode: stock.TsCode}).Where("ts_code = ?", stock.TsCode).Updates(stock)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//for _, item := range res.Data.Items {
|
|
||||||
// stock := &data.StockBasic{}
|
|
||||||
// stock.Exchange = convertor.ToString(item[0])
|
|
||||||
// stock.IsHs = convertor.ToString(item[1])
|
|
||||||
// stock.Name = convertor.ToString(item[2])
|
|
||||||
// stock.Industry = convertor.ToString(item[3])
|
|
||||||
// stock.ListStatus = convertor.ToString(item[4])
|
|
||||||
// stock.ActName = convertor.ToString(item[5])
|
|
||||||
// stock.ID = uint(item[6].(float64))
|
|
||||||
// stock.CurrType = convertor.ToString(item[7])
|
|
||||||
// stock.Area = convertor.ToString(item[8])
|
|
||||||
// stock.ListDate = convertor.ToString(item[9])
|
|
||||||
// stock.DelistDate = convertor.ToString(item[10])
|
|
||||||
// stock.ActEntType = convertor.ToString(item[11])
|
|
||||||
// stock.TsCode = convertor.ToString(item[12])
|
|
||||||
// stock.Symbol = convertor.ToString(item[13])
|
|
||||||
// stock.Cnspell = convertor.ToString(item[14])
|
|
||||||
// stock.Fullname = convertor.ToString(item[20])
|
|
||||||
// stock.Ename = convertor.ToString(item[21])
|
|
||||||
//
|
|
||||||
// var count int64
|
|
||||||
// db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).Count(&count)
|
|
||||||
// if count > 0 {
|
|
||||||
// continue
|
|
||||||
// } else {
|
|
||||||
// db.Dao.Create(stock)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkDir(dir string) {
|
func checkDir(dir string) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user