Compare commits
14 Commits
v2025.11.2
...
v2025.11.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4b3b61e8c | ||
|
|
b6a99940ab | ||
|
|
5b0f34a3bd | ||
|
|
e34ebf9895 | ||
|
|
c3521c6d7f | ||
|
|
93b37ca621 | ||
|
|
7069af869b | ||
|
|
dbb6789c05 | ||
|
|
8aed4d2753 | ||
|
|
6bd1bdae02 | ||
|
|
9a40d343aa | ||
|
|
e4cdad6ffe | ||
|
|
a0005dab96 | ||
|
|
c945ca9322 |
@@ -22,7 +22,7 @@
|
||||
- 开发环境主要基于Windows10+,其他平台未测试或功能受限。
|
||||
|
||||
### 📦 立即体验
|
||||
- 安装版:[go-stock-amd64-installer.exe](https://github.com/ArvinLovegood/go-stock/releases)
|
||||
[//]: # (- 安装版:[go-stock-amd64-installer.exe](https://github.com/ArvinLovegood/go-stock/releases))
|
||||
- 绿色版:[go-stock-windows-amd64.exe](https://github.com/ArvinLovegood/go-stock/releases)
|
||||
- MACOS绿色版:[go-stock-darwin-universal](https://github.com/ArvinLovegood/go-stock/releases)
|
||||
|
||||
|
||||
22
app.go
22
app.go
@@ -410,6 +410,10 @@ func (a *App) domReady(ctx context.Context) {
|
||||
//定时更新数据
|
||||
config := data.GetSettingConfig()
|
||||
go func() {
|
||||
go data.NewMarketNewsApi().TelegraphList(30)
|
||||
go data.NewMarketNewsApi().GetSinaNews(30)
|
||||
go data.NewMarketNewsApi().TradingViewNews()
|
||||
|
||||
interval := config.RefreshInterval
|
||||
if interval <= 0 {
|
||||
interval = 1
|
||||
@@ -453,6 +457,19 @@ func (a *App) domReady(ctx context.Context) {
|
||||
} else {
|
||||
a.cronEntrys["newSinaNews"] = entryIDSina
|
||||
}
|
||||
|
||||
entryIDTradingViewNews, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval+10), func() {
|
||||
news := data.NewMarketNewsApi().TradingViewNews()
|
||||
if config.EnablePushNews {
|
||||
go a.NewsPush(news)
|
||||
}
|
||||
go runtime.EventsEmit(a.ctx, "tradingViewNews", news)
|
||||
})
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("AddFunc error:%s", err.Error())
|
||||
} else {
|
||||
a.cronEntrys["tradingViewNews"] = entryIDTradingViewNews
|
||||
}
|
||||
}()
|
||||
|
||||
//刷新基金净值信息
|
||||
@@ -1358,8 +1375,9 @@ func (a *App) GetTelegraphList(source string) *[]*models.Telegraph {
|
||||
|
||||
func (a *App) ReFleshTelegraphList(source string) *[]*models.Telegraph {
|
||||
//data.NewMarketNewsApi().GetNewTelegraph(30)
|
||||
data.NewMarketNewsApi().TelegraphList(30)
|
||||
data.NewMarketNewsApi().GetSinaNews(30)
|
||||
go data.NewMarketNewsApi().TelegraphList(30)
|
||||
go data.NewMarketNewsApi().GetSinaNews(30)
|
||||
go data.NewMarketNewsApi().TradingViewNews()
|
||||
telegraphs := data.NewMarketNewsApi().GetTelegraphList(source)
|
||||
return telegraphs
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func (a *App) ChatWithAgent(question string, aiConfigId int, sysPromptId *int) {
|
||||
|
||||
func (a *App) AnalyzeSentimentWithFreqWeight(text string) map[string]any {
|
||||
if text == "" {
|
||||
telegraphs := data.NewMarketNewsApi().GetNews24HoursList("", 1000)
|
||||
telegraphs := data.NewMarketNewsApi().GetNews24HoursList("", 1000*10)
|
||||
messageText := strings.Builder{}
|
||||
for _, telegraph := range *telegraphs {
|
||||
messageText.WriteString(telegraph.Content + "\n")
|
||||
|
||||
@@ -3,13 +3,14 @@ package tools
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"go-stock/backend/data"
|
||||
"go-stock/backend/logger"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudwego/eino/components/tool"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
"github.com/tidwall/gjson"
|
||||
"go-stock/backend/data"
|
||||
"go-stock/backend/logger"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// @Author spark
|
||||
@@ -51,7 +52,7 @@ func (q QueryMarketNews) InvokableRun(ctx context.Context, argumentsInJSON strin
|
||||
})
|
||||
}
|
||||
|
||||
news := data.NewMarketNewsApi().GetNewsList("财联社电报", random.RandInt(100, 500))
|
||||
news := data.NewMarketNewsApi().GetNewsList("", random.RandInt(100, 500))
|
||||
messageText := strings.Builder{}
|
||||
for _, telegraph := range *news {
|
||||
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# 金融股票全场景分词字典(最终去重优化版)
|
||||
# 格式:单词 权重 词性 | 权重280-350分,核心术语优先匹配,无重复词汇
|
||||
# 覆盖:净买卖、股指、财务指标、交易操作、政策宏观、热点概念、机构媒体、美股中概股、十五五规划等全场景
|
||||
|
||||
# 一、净买卖与资金流向(核心交易表述)
|
||||
净卖出 340 v
|
||||
@@ -96,6 +95,7 @@
|
||||
操纵市场 300 n
|
||||
亏损 100 n
|
||||
加工 100 n
|
||||
|
||||
# 三、全球主要股指(含中英文缩写)
|
||||
# 中国市场
|
||||
A股 350 n
|
||||
@@ -117,63 +117,43 @@ A股 350 n
|
||||
科创50指数 330 n
|
||||
上证综指 350 n
|
||||
富时中国A50指数 340 n
|
||||
FTSE China A50 330 n
|
||||
恒生指数 340 n
|
||||
HSI 330 n
|
||||
恒生科技指数 340 n
|
||||
恒生国企指数 330 n
|
||||
H股指数 330 n
|
||||
# 美洲市场
|
||||
道琼斯工业平均指数 350 n
|
||||
DJIA 340 n
|
||||
标普500指数 350 n
|
||||
S&P 500 340 n
|
||||
纳斯达克综合指数 340 n
|
||||
纳斯达克100指数 340 n
|
||||
Nasdaq 100 330 n
|
||||
罗素2000指数 320 n
|
||||
Russell 2000 310 n
|
||||
标普400中型股指数 310 n
|
||||
标普600小型股指数 310 n
|
||||
纽约证交所综合指数 310 n
|
||||
NYSE Composite 300 n
|
||||
纳斯达克中国金龙指数 310 n
|
||||
# 欧洲市场
|
||||
德国DAX指数 330 n
|
||||
DAX 30 320 n
|
||||
法国CAC40指数 330 n
|
||||
CAC 40 320 n
|
||||
富时100指数 330 n
|
||||
FTSE 100 320 n
|
||||
欧元斯托克50指数 320 n
|
||||
Euro Stoxx 50 310 n
|
||||
英国富时250指数 310 n
|
||||
FTSE 250 300 n
|
||||
意大利富时MIB指数 310 n
|
||||
FTSE MIB 300 n
|
||||
西班牙IBEX 35指数 310 n
|
||||
IBEX 35 300 n
|
||||
# 亚太其他市场
|
||||
日经225指数 330 n
|
||||
Nikkei 225 320 n
|
||||
日经500指数 310 n
|
||||
韩国综合股价指数 320 n
|
||||
韩国kospi指数 320 n
|
||||
KOSPI 310 n
|
||||
澳洲标普200指数 310 n
|
||||
S&P/ASX 200 300 n
|
||||
印度孟买敏感指数 310 n
|
||||
Sensex 300 n
|
||||
印度Nifty 50指数 310 n
|
||||
Nifty 50 300 n
|
||||
# 全球综合指数
|
||||
MSCI指数 320 n
|
||||
MSCI全球指数 330 n
|
||||
MSCI World Index 320 n
|
||||
MSCI新兴市场指数 330 n
|
||||
MSCI Emerging Markets 320 n
|
||||
富时罗素全球指数 320 n
|
||||
FTSE Russell Global Index 310 n
|
||||
摩根大通全球债券指数 310 n
|
||||
全球股指 300 n
|
||||
发达市场指数 300 n
|
||||
@@ -198,38 +178,7 @@ G20国家指数 300 n
|
||||
指数估值 310 n
|
||||
指数市盈率 310 n
|
||||
|
||||
# 四、A股龙头公司(资讯高频)
|
||||
贵州茅台 310 n
|
||||
宁德时代 350 n
|
||||
比亚迪 340 n
|
||||
隆基绿能 300 n
|
||||
长江电力 290 n
|
||||
中国平安 300 n
|
||||
招商银行 300 n
|
||||
五粮液 290 n
|
||||
美的集团 290 n
|
||||
格力电器 290 n
|
||||
海康威视 290 n
|
||||
迈瑞医疗 290 n
|
||||
恒瑞医药 290 n
|
||||
中芯国际 300 n
|
||||
中兴通讯 290 n
|
||||
东方财富 290 n
|
||||
爱尔眼科 290 n
|
||||
通威股份 290 n
|
||||
药明康德 320 n
|
||||
阳光电源 290 n
|
||||
天齐锂业 290 n
|
||||
赣锋锂业 290 n
|
||||
中国中免 290 n
|
||||
海螺水泥 280 n
|
||||
万科A 280 n
|
||||
保利发展 280 n
|
||||
招商蛇口 280 n
|
||||
上汽集团 280 n
|
||||
宝钢股份 280 n
|
||||
|
||||
# 五、财务与估值核心指标
|
||||
# 四、财务与估值核心指标
|
||||
市盈率 350 n
|
||||
PE 350 n
|
||||
动态市盈率 340 n
|
||||
@@ -269,7 +218,7 @@ EPS 330 n
|
||||
量比 320 n
|
||||
振幅 320 n
|
||||
|
||||
# 六、政策与宏观经济
|
||||
# 五、政策与宏观经济
|
||||
货币政策 330 n
|
||||
财政政策 330 n
|
||||
稳健货币政策 320 n
|
||||
@@ -307,7 +256,7 @@ PMI 330 n
|
||||
黄金价格 310 n
|
||||
有色金属价格 300 n
|
||||
|
||||
# 七、金融产品与机构
|
||||
# 六、金融产品与机构
|
||||
股票 320 n
|
||||
基金 320 n
|
||||
公募基金 310 n
|
||||
@@ -351,7 +300,7 @@ QFII 300 n
|
||||
RQFII 290 n
|
||||
北向资金机构 300 n
|
||||
|
||||
# 八、热点概念与行业
|
||||
# 七、热点概念与行业
|
||||
AI 330 n
|
||||
人工智能 350 n
|
||||
算力 330 n
|
||||
@@ -395,7 +344,7 @@ CXO 300 n
|
||||
5G 300 n
|
||||
6G 340 n
|
||||
|
||||
# 九、交易操作与行情
|
||||
# 八、交易操作与行情
|
||||
上涨 310 v
|
||||
下跌 310 v
|
||||
涨停 310 v
|
||||
@@ -473,7 +422,7 @@ CXO 300 n
|
||||
震荡上行 320 v
|
||||
震荡下行 320 v
|
||||
|
||||
# 十、委托交易与规则
|
||||
# 九、委托交易与规则
|
||||
限价委托 340 n
|
||||
市价委托 340 n
|
||||
止损委托 330 n
|
||||
@@ -1,26 +1,185 @@
|
||||
公司 0.1 n
|
||||
国家 0.1 n
|
||||
国际 0.1 n
|
||||
会议 0.1 n
|
||||
市场 0.1 n
|
||||
经济 0.1 n
|
||||
技术 0.1 n
|
||||
记者 0.1 n
|
||||
时间 0.1 n
|
||||
项目 0.1 n
|
||||
问题 0.1 n
|
||||
企业 0.1 n
|
||||
财联社 0.1 n
|
||||
上涨 0.1 v
|
||||
下跌 0.1 v
|
||||
期货 0.1 n
|
||||
跌幅 0.1 n
|
||||
跌超 0.1 adj
|
||||
股票 0.1 n
|
||||
# 补充:热点概念与板块(Jieba/gse兼容格式)
|
||||
# 权重说明:核心热点500-700分,事件类400分,负权重词汇按需求保留
|
||||
|
||||
# 一、负权重低优先级词汇(减少无差别匹配干扰)
|
||||
公司 -0.1 n
|
||||
国家 -0.1 n
|
||||
国际 -0.1 n
|
||||
会议 -0.1 n
|
||||
市场 -0.1 n
|
||||
经济 -0.1 n
|
||||
技术 -0.1 n
|
||||
记者 -0.1 n
|
||||
时间 -0.1 n
|
||||
项目 -0.1 n
|
||||
问题 -0.1 n
|
||||
企业 -0.1 n
|
||||
财联社 -0.1 n
|
||||
上涨 -0.1 v
|
||||
下跌 -0.1 v
|
||||
期货 -0.1 n
|
||||
跌幅 -0.1 n
|
||||
跌超 -0.1 adj
|
||||
股票 -0.1 n
|
||||
基金 -0.1 n
|
||||
电讯 -0.1 n
|
||||
建筑 -0.1 n
|
||||
平开 -0.1 n
|
||||
保险 -0.1 n
|
||||
行业 -0.1 n
|
||||
其他 -0.1 n
|
||||
|
||||
# 二、核心热点概念(700分,最高优先级)
|
||||
比特币 700 n
|
||||
摩尔线程 700 n
|
||||
摩尔线程概念 700 n
|
||||
AI算力 700 n
|
||||
生成式AI 700 n
|
||||
量子计算 700 n
|
||||
脑机接口 700 n
|
||||
6G通信 700 n
|
||||
人形机器人 700 n
|
||||
固态电池 700 n
|
||||
ChatGPT概念 700 n
|
||||
Web3.0 700 n
|
||||
元宇宙 700 n
|
||||
数字孪生 700 n
|
||||
量子通信 700 n
|
||||
|
||||
# 三、重点赛道板块(500分,高优先级)
|
||||
冰雪旅游 500 n
|
||||
特高压 500 n
|
||||
跨境电商 500 n
|
||||
俄乌冲突 400 n
|
||||
新能源汽车 500 n
|
||||
机器人 500 n
|
||||
具身智能 500 n
|
||||
具身智能 500 n
|
||||
油气 500 n
|
||||
商业航天 500 n
|
||||
光伏储能 500 n
|
||||
锂电材料 500 n
|
||||
半导体设备 500 n
|
||||
集成电路 500 n
|
||||
创新药 500 n
|
||||
CXO 500 n
|
||||
医疗器械 500 n
|
||||
数字经济 500 n
|
||||
数字货币 500 n
|
||||
区块链 500 n
|
||||
低空经济 500 n
|
||||
工业互联网 500 n
|
||||
物联网 500 n
|
||||
5G应用 500 n
|
||||
充电桩 500 n
|
||||
氢能源 500 n
|
||||
核聚变 500 n
|
||||
工业母机 500 n
|
||||
新材料 500 n
|
||||
生物制造 500 n
|
||||
智能网联汽车 500 n
|
||||
乡村振兴 500 n
|
||||
国企改革 500 n
|
||||
央企重组 500 n
|
||||
跨境金融 500 n
|
||||
自贸港 500 n
|
||||
一带一路 500 n
|
||||
绿色低碳 500 n
|
||||
碳交易 500 n
|
||||
数据要素 500 n
|
||||
数字基建 500 n
|
||||
东数西算 500 n
|
||||
国产替代 500 n
|
||||
信创 500 n
|
||||
网络安全 500 n
|
||||
算力网络 500 n
|
||||
边缘计算 500 n
|
||||
虚拟现实 500 n
|
||||
增强现实 500 n
|
||||
智能穿戴 500 n
|
||||
智能家居 500 n
|
||||
车联网 500 n
|
||||
激光雷达 500 n
|
||||
氮化镓 500 n
|
||||
碳化硅 500 n
|
||||
第三代半导体 500 n
|
||||
EDA工具 500 n
|
||||
光刻胶 500 n
|
||||
芯片设计 500 n
|
||||
封装测试 500 n
|
||||
储能电池 500 n
|
||||
钠离子电池 500 n
|
||||
氢燃料电池 500 n
|
||||
光伏组件 500 n
|
||||
风电设备 500 n
|
||||
特高压设备 500 n
|
||||
电力物联网 500 n
|
||||
智能电网 500 n
|
||||
轨道交通 500 n
|
||||
航空航天 500 n
|
||||
海洋工程 500 n
|
||||
高端装备 500 n
|
||||
军工电子 500 n
|
||||
卫星互联网 500 n
|
||||
北斗导航 500 n
|
||||
国产大飞机 500 n
|
||||
生物医药 500 n
|
||||
基因测序 500 n
|
||||
疫苗 500 n
|
||||
医疗美容 500 n
|
||||
养老产业 500 n
|
||||
教育信息化 500 n
|
||||
体育产业 500 n
|
||||
文化创意 500 n
|
||||
旅游复苏 500 n
|
||||
预制菜 500 n
|
||||
白酒 500 n
|
||||
食品饮料 500 n
|
||||
家电下乡 500 n
|
||||
房地产复苏 500 n
|
||||
基建投资 500 n
|
||||
新型城镇化 500 n
|
||||
冷链物流 500 n
|
||||
快递物流 500 n
|
||||
跨境支付 500 n
|
||||
金融科技 500 n
|
||||
消费电子 500 n
|
||||
元宇宙基建 500 n
|
||||
数字藏品 500 n
|
||||
NFT 500 n
|
||||
绿色电力 500 n
|
||||
节能降碳 500 n
|
||||
抽水蓄能 500 n
|
||||
生物质能 500 n
|
||||
地热能 500 n
|
||||
潮汐能 500 n
|
||||
|
||||
# 四、事件驱动型概念(400分,中优先级)
|
||||
俄乌冲突 400 n
|
||||
中东局势 400 n
|
||||
美联储加息 400 n
|
||||
降息预期 400 n
|
||||
贸易摩擦 400 n
|
||||
供应链重构 400 n
|
||||
能源危机 400 n
|
||||
粮食安全 400 n
|
||||
疫情复苏 400 n
|
||||
政策利好 400 n
|
||||
产业扶持 400 n
|
||||
技术突破 400 n
|
||||
并购重组 400 n
|
||||
IPO提速 400 n
|
||||
解禁潮 400 n
|
||||
北向资金流入 400 n
|
||||
南向资金流入 400 n
|
||||
主力资金异动 400 n
|
||||
行业景气度 400 n
|
||||
业绩预增 400 n
|
||||
商誉减值 400 n
|
||||
退市风险 400 n
|
||||
监管新规 400 n
|
||||
税收优惠 400 n
|
||||
补贴政策 400 n
|
||||
基建刺激 400 n
|
||||
消费刺激 400 n
|
||||
新能源补贴 400 n
|
||||
碳达峰政策 400 n
|
||||
碳中和目标 400 n
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"go-stock/backend/logger"
|
||||
"go-stock/backend/models"
|
||||
"go-stock/backend/util"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -53,7 +54,7 @@ func (m MarketNewsApi) TelegraphList(crawlTimeOut int64) *[]models.Telegraph {
|
||||
for _, v := range rollData {
|
||||
news := v.(map[string]any)
|
||||
ctime, _ := convertor.ToInt(news["ctime"])
|
||||
dataTime := time.Unix(ctime, 0)
|
||||
dataTime := time.Unix(ctime, 0).Local()
|
||||
logger.SugaredLogger.Debugf("dataTime: %s", dataTime)
|
||||
telegraph := models.Telegraph{
|
||||
Content: news["content"].(string),
|
||||
@@ -61,7 +62,7 @@ func (m MarketNewsApi) TelegraphList(crawlTimeOut int64) *[]models.Telegraph {
|
||||
DataTime: &dataTime,
|
||||
Url: news["shareurl"].(string),
|
||||
Source: "财联社电报",
|
||||
IsRed: GetLevel(news["level"].(string)),
|
||||
IsRed: (news["level"].(string)) != "C",
|
||||
SentimentResult: AnalyzeSentiment(news["content"].(string)).Description,
|
||||
}
|
||||
cnt := int64(0)
|
||||
@@ -96,9 +97,6 @@ func (m MarketNewsApi) TelegraphList(crawlTimeOut int64) *[]models.Telegraph {
|
||||
|
||||
return &telegraphs
|
||||
}
|
||||
func GetLevel(s string) bool {
|
||||
return s > "C"
|
||||
}
|
||||
|
||||
func (m MarketNewsApi) GetNewTelegraph(crawlTimeOut int64) *[]models.Telegraph {
|
||||
url := "https://www.cls.cn/telegraph"
|
||||
@@ -167,9 +165,9 @@ func (m MarketNewsApi) GetNewTelegraph(crawlTimeOut int64) *[]models.Telegraph {
|
||||
func (m MarketNewsApi) GetNewsList(source string, limit int) *[]*models.Telegraph {
|
||||
news := &[]*models.Telegraph{}
|
||||
if source != "" {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("id desc").Limit(limit).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("data_time desc,time desc").Limit(limit).Find(news)
|
||||
} else {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Order("id desc").Limit(limit).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Order("data_time desc,time desc").Limit(limit).Find(news)
|
||||
}
|
||||
for _, item := range *news {
|
||||
tags := &[]models.Tags{}
|
||||
@@ -188,9 +186,9 @@ func (m MarketNewsApi) GetNewsList2(source string, limit int) *[]*models.Telegra
|
||||
NewMarketNewsApi().TelegraphList(30)
|
||||
news := &[]*models.Telegraph{}
|
||||
if source != "" {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("id desc,is_red desc").Limit(limit).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("data_time desc,is_red desc").Limit(limit).Find(news)
|
||||
} else {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Order("id desc,is_red desc").Limit(limit).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Order("data_time desc,is_red desc").Limit(limit).Find(news)
|
||||
}
|
||||
for _, item := range *news {
|
||||
tags := &[]models.Tags{}
|
||||
@@ -209,9 +207,9 @@ func (m MarketNewsApi) GetNewsList2(source string, limit int) *[]*models.Telegra
|
||||
func (m MarketNewsApi) GetTelegraphList(source string) *[]*models.Telegraph {
|
||||
news := &[]*models.Telegraph{}
|
||||
if source != "" {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("id desc").Limit(20).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("data_time desc,time desc").Limit(50).Find(news)
|
||||
} else {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Order("id desc").Limit(20).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Order("data_time desc,time desc").Limit(50).Find(news)
|
||||
}
|
||||
for _, item := range *news {
|
||||
tags := &[]models.Tags{}
|
||||
@@ -268,6 +266,10 @@ func (m MarketNewsApi) GetSinaNews(crawlTimeOut uint) *[]models.Telegraph {
|
||||
//logger.SugaredLogger.Infof("%s:%s", data["create_time"], data["rich_text"])
|
||||
telegraph.Content = data["rich_text"].(string)
|
||||
telegraph.Time = strings.Split(data["create_time"].(string), " ")[1]
|
||||
dataTime, _ := time.ParseInLocation("2006-01-02 15:04:05", data["create_time"].(string), time.Local)
|
||||
if &dataTime != nil {
|
||||
telegraph.DataTime = &dataTime
|
||||
}
|
||||
tags := data["tag"].([]any)
|
||||
telegraph.SubjectTags = lo.Map(tags, func(tagItem any, index int) string {
|
||||
name := tagItem.(map[string]any)["name"].(string)
|
||||
@@ -286,7 +288,7 @@ func (m MarketNewsApi) GetSinaNews(crawlTimeOut uint) *[]models.Telegraph {
|
||||
if telegraph.Content != "" {
|
||||
telegraph.SentimentResult = AnalyzeSentiment(telegraph.Content).Description
|
||||
cnt := int64(0)
|
||||
db.Dao.Model(telegraph).Where("time=? and source=?", telegraph.Time, telegraph.Source).Count(&cnt)
|
||||
db.Dao.Model(telegraph).Where("content=? and source=?", telegraph.Content, telegraph.Source).Count(&cnt)
|
||||
if cnt == 0 {
|
||||
db.Dao.Create(&telegraph)
|
||||
telegraphs = append(telegraphs, telegraph)
|
||||
@@ -640,14 +642,16 @@ func (m MarketNewsApi) EMDictCode(code string, cache *freecache.Cache) []any {
|
||||
return respMap["data"].([]any)
|
||||
}
|
||||
|
||||
func (m MarketNewsApi) TradingViewNews() *[]models.TVNews {
|
||||
func (m MarketNewsApi) TradingViewNews() *[]models.Telegraph {
|
||||
client := resty.New()
|
||||
config := GetSettingConfig()
|
||||
if config.HttpProxyEnabled && config.HttpProxy != "" {
|
||||
client.SetProxy(config.HttpProxy)
|
||||
}
|
||||
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"
|
||||
news := &[]models.Telegraph{}
|
||||
// url := "https://news-mediator.tradingview.com/news-flow/v2/news?filter=lang:zh-Hans&filter=area:WLD&client=screener&streaming=false"
|
||||
url := "https://news-mediator.tradingview.com/news-flow/v2/news?filter=area%3AWLD&filter=lang%3Azh-Hans&client=screener&streaming=false"
|
||||
resp, err := client.SetTimeout(time.Duration(5)*time.Second).R().
|
||||
SetHeader("Host", "news-mediator.tradingview.com").
|
||||
SetHeader("Origin", "https://cn.tradingview.com").
|
||||
@@ -656,19 +660,81 @@ func (m MarketNewsApi) TradingViewNews() *[]models.TVNews {
|
||||
Get(url)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("TradingViewNews err:%s", err.Error())
|
||||
return TVNews
|
||||
return news
|
||||
}
|
||||
respMap := map[string]any{}
|
||||
err = json.Unmarshal(resp.Body(), &respMap)
|
||||
if err != nil {
|
||||
return TVNews
|
||||
return news
|
||||
}
|
||||
items, err := json.Marshal(respMap["items"])
|
||||
if err != nil {
|
||||
return TVNews
|
||||
return news
|
||||
}
|
||||
json.Unmarshal(items, TVNews)
|
||||
return TVNews
|
||||
|
||||
for i, a := range *TVNews {
|
||||
if i > 10 {
|
||||
break
|
||||
}
|
||||
detail := NewMarketNewsApi().TradingViewNewsDetail(a.Id)
|
||||
dataTime := time.Unix(int64(a.Published), 0).Local()
|
||||
description := ""
|
||||
sentimentResult := ""
|
||||
if detail != nil {
|
||||
description = detail.ShortDescription
|
||||
sentimentResult = AnalyzeSentiment(description).Description
|
||||
}
|
||||
if a.Title == "" {
|
||||
continue
|
||||
}
|
||||
telegraph := &models.Telegraph{
|
||||
Title: a.Title,
|
||||
Content: description,
|
||||
DataTime: &dataTime,
|
||||
IsRed: false,
|
||||
Time: dataTime.Format("15:04:05"),
|
||||
Source: "外媒",
|
||||
Url: fmt.Sprintf("https://cn.tradingview.com/news/%s", a.Id),
|
||||
SentimentResult: sentimentResult,
|
||||
}
|
||||
cnt := int64(0)
|
||||
db.Dao.Model(telegraph).Where("time=? and title=? and source=?", telegraph.Time, telegraph.Title, "外媒").Count(&cnt)
|
||||
if cnt > 0 {
|
||||
continue
|
||||
}
|
||||
db.Dao.Model(&models.Telegraph{}).Where("time=? and title=? and source=?", telegraph.Time, telegraph.Title, "外媒").FirstOrCreate(&telegraph)
|
||||
*news = append(*news, *telegraph)
|
||||
}
|
||||
return news
|
||||
}
|
||||
func (m MarketNewsApi) TradingViewNewsDetail(id string) *models.TVNewsDetail {
|
||||
//https://news-headlines.tradingview.com/v3/story?id=panews%3A9be7cf057e3f9%3A0&lang=zh-Hans
|
||||
newsDetail := &models.TVNewsDetail{}
|
||||
newsUrl := fmt.Sprintf("https://news-headlines.tradingview.com/v3/story?id=%s&lang=zh-Hans", url.QueryEscape(id))
|
||||
|
||||
client := resty.New()
|
||||
config := GetSettingConfig()
|
||||
if config.HttpProxyEnabled && config.HttpProxy != "" {
|
||||
client.SetProxy(config.HttpProxy)
|
||||
}
|
||||
request := client.SetTimeout(time.Duration(3) * time.Second).R()
|
||||
_, err := request.
|
||||
SetHeader("Host", "news-headlines.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:146.0) Gecko/20100101 Firefox/146.0").
|
||||
//SetHeader("TE", "trailers").
|
||||
//SetHeader("Priority", "u=4").
|
||||
//SetHeader("Connection", "keep-alive").
|
||||
SetResult(newsDetail).
|
||||
Get(newsUrl)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("TradingViewNewsDetail err:%s", err.Error())
|
||||
return newsDetail
|
||||
}
|
||||
logger.SugaredLogger.Infof("resp:%+v", newsDetail)
|
||||
return newsDetail
|
||||
}
|
||||
|
||||
func (m MarketNewsApi) XUEQIUHotStock(size int, marketType string) *[]models.HotItem {
|
||||
@@ -1031,9 +1097,9 @@ func (m MarketNewsApi) CailianpressWeb(searchWords string) *models.CailianpressW
|
||||
func (m MarketNewsApi) GetNews24HoursList(source string, limit int) *[]*models.Telegraph {
|
||||
news := &[]*models.Telegraph{}
|
||||
if source != "" {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=? and created_at>?", source, time.Now().Add(-24*time.Hour)).Order("id desc,is_red desc").Limit(limit).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=? and created_at>?", source, time.Now().Add(-24*time.Hour)).Order("data_time desc,is_red desc").Limit(limit).Find(news)
|
||||
} else {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("created_at>?", time.Now().Add(-24*time.Hour)).Order("id desc,is_red desc").Limit(limit).Find(news)
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("created_at>?", time.Now().Add(-24*time.Hour)).Order("data_time desc,is_red desc").Limit(limit).Find(news)
|
||||
}
|
||||
// 内容去重
|
||||
uniqueNews := make([]*models.Telegraph, 0)
|
||||
|
||||
@@ -21,7 +21,12 @@ import (
|
||||
|
||||
func TestGetSinaNews(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
NewMarketNewsApi().GetSinaNews(30)
|
||||
InitAnalyzeSentiment()
|
||||
news := NewMarketNewsApi().GetSinaNews(30)
|
||||
for i, telegraph := range *news {
|
||||
logger.SugaredLogger.Debugf("key: %+v, value: %+v", i, telegraph)
|
||||
|
||||
}
|
||||
//NewMarketNewsApi().GetNewTelegraph(30)
|
||||
|
||||
}
|
||||
@@ -122,10 +127,8 @@ func TestEMDictCode(t *testing.T) {
|
||||
|
||||
func TestTradingViewNews(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
resp := NewMarketNewsApi().TradingViewNews()
|
||||
for _, a := range *resp {
|
||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
||||
}
|
||||
InitAnalyzeSentiment()
|
||||
NewMarketNewsApi().TradingViewNews()
|
||||
}
|
||||
|
||||
func TestXUEQIUHotStock(t *testing.T) {
|
||||
@@ -247,5 +250,6 @@ func TestGetNewsList2(t *testing.T) {
|
||||
|
||||
func TestTelegraphList(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
InitAnalyzeSentiment()
|
||||
NewMarketNewsApi().TelegraphList(30)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,13 @@ func NewSearchStockApi(words string) *SearchStockApi {
|
||||
return &SearchStockApi{words: words}
|
||||
}
|
||||
func (s SearchStockApi) SearchStock(pageSize int) map[string]any {
|
||||
qgqpBId := NewSettingsApi().Config.QgqpBId
|
||||
if qgqpBId == "" {
|
||||
return map[string]any{
|
||||
"code": -1,
|
||||
"message": "请先获取东财用户标识(qgqp_b_id):打开浏览器,访问东财网站,按F12打开开发人员工具-》网络面板,随便点开一个请求,复制请求cookie中qgqp_b_id对应的值。保存到设置中的东财唯一标识输入框",
|
||||
}
|
||||
}
|
||||
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").
|
||||
@@ -32,22 +39,25 @@ func (s SearchStockApi) SearchStock(pageSize int) map[string]any {
|
||||
"keyWord": "%s",
|
||||
"pageSize": %d,
|
||||
"pageNo": 1,
|
||||
"fingerprint": "02efa8944b1f90fbfe050e1e695a480d",
|
||||
"fingerprint": "%s",
|
||||
"gids": [],
|
||||
"matchWord": "",
|
||||
"timestamp": "%d",
|
||||
"shareToGuba": false,
|
||||
"requestId": "RMd3Y76AJI98axPvdhdbKvbBDVwLlUK61761559950168",
|
||||
"requestId": "",
|
||||
"needCorrect": true,
|
||||
"removedConditionIdList": [],
|
||||
"xcId": "xc0d61279aad33008260",
|
||||
"xcId": "",
|
||||
"ownSelectAll": false,
|
||||
"dxInfo": [],
|
||||
"extraCondition": ""
|
||||
}`, s.words, pageSize, time.Now().Unix())).Post(url)
|
||||
}`, s.words, pageSize, qgqpBId, time.Now().Unix())).Post(url)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("SearchStock-err:%+v", err)
|
||||
return map[string]any{}
|
||||
return map[string]any{
|
||||
"code": -1,
|
||||
"message": err.Error(),
|
||||
}
|
||||
}
|
||||
respMap := map[string]any{}
|
||||
json.Unmarshal(resp.Body(), &respMap)
|
||||
|
||||
@@ -4,14 +4,22 @@ import (
|
||||
"encoding/json"
|
||||
"go-stock/backend/db"
|
||||
"go-stock/backend/logger"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func TestSearchStock(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
|
||||
e := convertor.ToString(math.Floor(float64(9*random.RandFloat(0, 1, 12) + 1)))
|
||||
for i := 0; i < 19; i++ {
|
||||
e += convertor.ToString(math.Floor(float64(9 * random.RandFloat(0, 1, 12))))
|
||||
}
|
||||
logger.SugaredLogger.Infof("e:%s", e)
|
||||
|
||||
res := NewSearchStockApi("量比大于2,基本面优秀,2025年三季报已披露,主力连续3日净流入,非创业板非科创板非ST").SearchStock(20)
|
||||
logger.SugaredLogger.Infof("res:%+v", res)
|
||||
data := res["data"].(map[string]any)
|
||||
|
||||
@@ -37,6 +37,7 @@ type Settings struct {
|
||||
HttpProxy string `json:"httpProxy"`
|
||||
HttpProxyEnabled bool `json:"httpProxyEnabled"`
|
||||
EnableAgent bool `json:"enableAgent"`
|
||||
QgqpBId string `json:"qgqpBId" gorm:"column:qgqp_b_id"`
|
||||
}
|
||||
|
||||
func (receiver Settings) TableName() string {
|
||||
@@ -108,6 +109,7 @@ func UpdateConfig(s *SettingConfig) string {
|
||||
"http_proxy": s.HttpProxy,
|
||||
"http_proxy_enabled": s.HttpProxyEnabled,
|
||||
"enable_agent": s.EnableAgent,
|
||||
"qgqp_b_id": s.QgqpBId,
|
||||
})
|
||||
|
||||
//更新AiConfig
|
||||
|
||||
@@ -38,14 +38,14 @@ var (
|
||||
|
||||
// 负面金融词汇及其权重
|
||||
negativeFinanceWords = map[string]float64{
|
||||
"跌": 1.0, "下跌": 2.0, "跌停": 3.0, "熊市": 3.0, "回调": 1.5, "新低": 2.5,
|
||||
"跌": 2.0, "下跌": 2.0, "跌停": 3.0, "熊市": 3.0, "回调": 2.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,
|
||||
"衰退": 2.0, "跌破": 2.0, "创新低": 3.0, "走弱": 2.5, "下挫": 2.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, "跌超": 2.5, "跌逾": 2.5,
|
||||
"被抓": 3.0, "被抓捕": 3.0,
|
||||
"垃圾股": 2.0, "风险股": 2.0, "弱势": 2.5, "走低": 2.5, "缩量": 2.5,
|
||||
"大跌": 2.5, "暴跌": 3.0, "崩盘": 3.0, "跳水": 3.0, "重挫": 3.0, "跌超": 2.5, "跌逾": 2.5, "跌近": 3.0,
|
||||
"被抓": 3.0, "被抓捕": 3.0, "回吐": 3.0, "转跌": 3.0,
|
||||
}
|
||||
|
||||
// 否定词,用于反转情感极性
|
||||
@@ -88,9 +88,9 @@ func InitAnalyzeSentiment() {
|
||||
if strutil.Trim(stock.Name) == "" {
|
||||
continue
|
||||
}
|
||||
err := seg.AddToken(stock.Name, basefreq+500, "n")
|
||||
err := seg.AddToken(stock.Name, basefreq+100, "n")
|
||||
if strutil.Trim(stock.BKName) != "" {
|
||||
err = seg.AddToken(stock.BKName, basefreq+500, "n")
|
||||
err = seg.AddToken(stock.BKName, basefreq+100, "n")
|
||||
}
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("添加%s失败:%s", stock.Name, err.Error())
|
||||
@@ -102,9 +102,9 @@ func InitAnalyzeSentiment() {
|
||||
if strutil.Trim(stock.Name) == "" {
|
||||
continue
|
||||
}
|
||||
err := seg.AddToken(stock.Name, basefreq+500, "n")
|
||||
err := seg.AddToken(stock.Name, basefreq+100, "n")
|
||||
if strutil.Trim(stock.BKName) != "" {
|
||||
err = seg.AddToken(stock.BKName, basefreq+500, "n")
|
||||
err = seg.AddToken(stock.BKName, basefreq+100, "n")
|
||||
}
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("添加%s失败:%s", stock.Name, err.Error())
|
||||
@@ -119,9 +119,9 @@ func InitAnalyzeSentiment() {
|
||||
// }
|
||||
//}
|
||||
tags := &[]models.Tags{}
|
||||
db.Dao.Model(&models.Tags{}).Find(tags)
|
||||
db.Dao.Model(&models.Tags{}).Where("type = ?", "subject").Find(tags)
|
||||
for _, tag := range *tags {
|
||||
err := seg.AddToken(tag.Name, basefreq, "n")
|
||||
err := seg.ReAddToken(tag.Name, basefreq+100, "n")
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("添加%s失败:%s", tag.Name, err.Error())
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func InitAnalyzeSentiment() {
|
||||
k := strutil.SplitAndTrim(line, " ")
|
||||
switch len(k) {
|
||||
case 1:
|
||||
err = seg.ReAddToken(k[0], 100)
|
||||
err = seg.ReAddToken(k[0], basefreq)
|
||||
case 2:
|
||||
freq, _ := convertor.ToFloat(k[1])
|
||||
err = seg.ReAddToken(k[0], freq)
|
||||
@@ -267,7 +267,7 @@ func countWordFrequencyWithWeight(text string) map[string]WordFreqWithWeight {
|
||||
// 构建包含权重的结果
|
||||
for word, frequency := range wordCount {
|
||||
weight := getWordWeight(word)
|
||||
if weight > 200 {
|
||||
if weight > basefreq {
|
||||
freqMap[word] = WordFreqWithWeight{
|
||||
Word: word,
|
||||
Frequency: frequency,
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/plugin/dbresolver"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Dao *gorm.DB
|
||||
@@ -26,7 +27,7 @@ func Init(sqlitePath string) {
|
||||
var openDb *gorm.DB
|
||||
var err error
|
||||
if sqlitePath == "" {
|
||||
sqlitePath = "data/stock.db?cache=shared&mode=rwc&_journal_mode=WAL"
|
||||
sqlitePath = "data/stock.db?cache_size=-524288&journal_mode=WAL"
|
||||
}
|
||||
openDb, err = gorm.Open(sqlite.Open(sqlitePath), &gorm.Config{
|
||||
Logger: dbLogger,
|
||||
@@ -48,8 +49,8 @@ func Init(sqlitePath string) {
|
||||
if err != nil {
|
||||
log.Fatalf("openDb.DB error is %s", err.Error())
|
||||
}
|
||||
dbCon.SetMaxIdleConns(10)
|
||||
dbCon.SetMaxOpenConns(100)
|
||||
dbCon.SetMaxIdleConns(4)
|
||||
dbCon.SetMaxOpenConns(10)
|
||||
dbCon.SetConnMaxLifetime(time.Hour)
|
||||
Dao = openDb
|
||||
}
|
||||
|
||||
@@ -232,15 +232,16 @@ type Prompt struct {
|
||||
type Telegraph struct {
|
||||
gorm.Model
|
||||
Time string `json:"time"`
|
||||
DataTime *time.Time `json:"dataTime"`
|
||||
Content string `json:"content"`
|
||||
DataTime *time.Time `json:"dataTime" gorm:"index"`
|
||||
Title string `json:"title" gorm:"index"`
|
||||
Content string `json:"content" gorm:"index"`
|
||||
SubjectTags []string `json:"subjects" gorm:"-:all"`
|
||||
StocksTags []string `json:"stocks" gorm:"-:all"`
|
||||
IsRed bool `json:"isRed"`
|
||||
IsRed bool `json:"isRed" gorm:"index"`
|
||||
Url string `json:"url"`
|
||||
Source string `json:"source"`
|
||||
Source string `json:"source" gorm:"index"`
|
||||
TelegraphTags []TelegraphTags `json:"tags" gorm:"-:migration;foreignKey:TelegraphId"`
|
||||
SentimentResult string `json:"sentimentResult"`
|
||||
SentimentResult string `json:"sentimentResult" gorm:"index"`
|
||||
}
|
||||
type TelegraphTags struct {
|
||||
gorm.Model
|
||||
@@ -331,6 +332,22 @@ type TVNews struct {
|
||||
LogoId string `json:"logo_id"`
|
||||
} `json:"provider"`
|
||||
}
|
||||
type TVNewsDetail struct {
|
||||
ShortDescription string `json:"shortDescription"`
|
||||
Tags []struct {
|
||||
Title string `json:"title"`
|
||||
Args []struct {
|
||||
Id string `json:"id"`
|
||||
Value string `json:"value"`
|
||||
} `json:"args"`
|
||||
} `json:"tags"`
|
||||
Copyright string `json:"copyright"`
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Published int `json:"published"`
|
||||
Urgency int `json:"urgency"`
|
||||
StoryPath string `json:"storyPath"`
|
||||
}
|
||||
|
||||
type XUEQIUHot struct {
|
||||
Data struct {
|
||||
|
||||
132
frontend/package-lock.json
generated
132
frontend/package-lock.json
generated
@@ -33,14 +33,14 @@
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"@vicons/material": "^0.13.0",
|
||||
"@vicons/tabler": "^0.13.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue": "^6.0.2",
|
||||
"html-docx-js-typescript": "^0.1.5",
|
||||
"less": "^4.4.0",
|
||||
"naive-ui": "^2.41.0",
|
||||
"naive-ui": "^2.43.2",
|
||||
"unplugin-auto-import": "^20.0.0",
|
||||
"unplugin-vue-components": "^29.0.0",
|
||||
"vfonts": "^0.0.3",
|
||||
"vite": "^6.3.5"
|
||||
"vite": "7.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -480,6 +480,7 @@
|
||||
"resolved": "https://registry.npmmirror.com/@css-render/vue3-ssr/-/vue3-ssr-0.15.14.tgz",
|
||||
"integrity": "sha512-//8027GSbxE9n3QlD73xFY6z4ZbHbvrOVB7AO6hsmrEzGbg+h2A09HboUyDgu+xsmj7JnvJD39Irt+2D0+iV8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.11"
|
||||
}
|
||||
@@ -924,7 +925,8 @@
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
@@ -1115,6 +1117,13 @@
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0-beta.50",
|
||||
"resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz",
|
||||
"integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz",
|
||||
@@ -1486,9 +1495,10 @@
|
||||
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw=="
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash-es": {
|
||||
"version": "4.17.12",
|
||||
@@ -1602,15 +1612,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vitejs/plugin-vue": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz",
|
||||
"integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz",
|
||||
"integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rolldown/pluginutils": "1.0.0-beta.50"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^5.0.0 || ^6.0.0",
|
||||
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
||||
"vue": "^3.2.25"
|
||||
}
|
||||
},
|
||||
@@ -2100,7 +2114,8 @@
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/evtd/-/evtd-0.2.4.tgz",
|
||||
"integrity": "sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/exsolve": {
|
||||
"version": "1.0.7",
|
||||
@@ -2110,11 +2125,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fdir": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
|
||||
"integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
|
||||
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"picomatch": "^3 || ^4"
|
||||
},
|
||||
@@ -2603,46 +2621,36 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/naive-ui": {
|
||||
"version": "2.41.0",
|
||||
"resolved": "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.41.0.tgz",
|
||||
"integrity": "sha512-KnmLg+xPLwXV8QVR7ZZ69eCjvel7R5vru8+eFe4VoAJHEgqAJgVph6Zno9K2IVQRpSF3GBGea3tjavslOR4FAA==",
|
||||
"version": "2.43.2",
|
||||
"resolved": "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.43.2.tgz",
|
||||
"integrity": "sha512-YlLMnGrwGTOc+zMj90sG3ubaH5/7czsgLgGcjTLA981IUaz8r6t4WIujNt8r9PNr+dqv6XNEr0vxkARgPPjfBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@css-render/plugin-bem": "^0.15.14",
|
||||
"@css-render/vue3-ssr": "^0.15.14",
|
||||
"@types/katex": "^0.16.2",
|
||||
"@types/lodash": "^4.14.198",
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"async-validator": "^4.2.5",
|
||||
"css-render": "^0.15.14",
|
||||
"csstype": "^3.1.3",
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns-tz": "^3.1.3",
|
||||
"date-fns": "^4.1.0",
|
||||
"date-fns-tz": "^3.2.0",
|
||||
"evtd": "^0.2.4",
|
||||
"highlight.js": "^11.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"seemly": "^0.3.8",
|
||||
"seemly": "^0.3.10",
|
||||
"treemate": "^0.3.11",
|
||||
"vdirs": "^0.1.8",
|
||||
"vooks": "^0.2.12",
|
||||
"vueuc": "^0.4.63"
|
||||
"vueuc": "^0.4.65"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/naive-ui/node_modules/date-fns": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-3.6.0.tgz",
|
||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
@@ -2930,7 +2938,8 @@
|
||||
"version": "0.3.10",
|
||||
"resolved": "https://registry.npmmirror.com/seemly/-/seemly-0.3.10.tgz",
|
||||
"integrity": "sha512-2+SMxtG1PcsL0uyhkumlOU6Qo9TAQ/WyH7tthnPIOQB05/12jz9naq6GZ6iZ6ApVsO3rr2gsnTf3++OV63kE1Q==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/select": {
|
||||
"version": "1.1.2",
|
||||
@@ -3074,14 +3083,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
|
||||
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fdir": "^6.4.4",
|
||||
"picomatch": "^4.0.2"
|
||||
"fdir": "^6.5.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
@@ -3309,6 +3318,7 @@
|
||||
"resolved": "https://registry.npmmirror.com/vdirs/-/vdirs-0.1.8.tgz",
|
||||
"integrity": "sha512-H9V1zGRLQZg9b+GdMk8MXDN2Lva0zx72MPahDKc30v+DtwKjfyOSXWRIX4t2mhDubM1H09gPhWeth/BJWPHGUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"evtd": "^0.2.2"
|
||||
},
|
||||
@@ -3323,24 +3333,24 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.3.5",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
|
||||
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
|
||||
"version": "7.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-7.2.4.tgz",
|
||||
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
"picomatch": "^4.0.2",
|
||||
"postcss": "^8.5.3",
|
||||
"rollup": "^4.34.9",
|
||||
"tinyglobby": "^0.2.13"
|
||||
"fdir": "^6.5.0",
|
||||
"picomatch": "^4.0.3",
|
||||
"postcss": "^8.5.6",
|
||||
"rollup": "^4.43.0",
|
||||
"tinyglobby": "^0.2.15"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vitejs/vite?sponsor=1"
|
||||
@@ -3349,14 +3359,14 @@
|
||||
"fsevents": "~2.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||
"@types/node": "^20.19.0 || >=22.12.0",
|
||||
"jiti": ">=1.21.0",
|
||||
"less": "*",
|
||||
"less": "^4.0.0",
|
||||
"lightningcss": "^1.21.0",
|
||||
"sass": "*",
|
||||
"sass-embedded": "*",
|
||||
"stylus": "*",
|
||||
"sugarss": "*",
|
||||
"sass": "^1.70.0",
|
||||
"sass-embedded": "^1.70.0",
|
||||
"stylus": ">=0.54.8",
|
||||
"sugarss": "^5.0.0",
|
||||
"terser": "^5.16.0",
|
||||
"tsx": "^4.8.1",
|
||||
"yaml": "^2.4.2"
|
||||
@@ -3442,6 +3452,7 @@
|
||||
"resolved": "https://registry.npmmirror.com/vooks/-/vooks-0.2.12.tgz",
|
||||
"integrity": "sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"evtd": "^0.2.2"
|
||||
},
|
||||
@@ -3493,10 +3504,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vueuc": {
|
||||
"version": "0.4.64",
|
||||
"resolved": "https://registry.npmmirror.com/vueuc/-/vueuc-0.4.64.tgz",
|
||||
"integrity": "sha512-wlJQj7fIwKK2pOEoOq4Aro8JdPOGpX8aWQhV8YkTW9OgWD2uj2O8ANzvSsIGjx7LTOc7QbS7sXdxHi6XvRnHPA==",
|
||||
"version": "0.4.65",
|
||||
"resolved": "https://registry.npmmirror.com/vueuc/-/vueuc-0.4.65.tgz",
|
||||
"integrity": "sha512-lXuMl+8gsBmruudfxnMF9HW4be8rFziylXFu1VHVNbLVhRTXXV4njvpRuJapD/8q+oFEMSfQMH16E/85VoWRyQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@css-render/vue3-ssr": "^0.15.10",
|
||||
"@juggle/resize-observer": "^3.3.1",
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"@vicons/material": "^0.13.0",
|
||||
"@vicons/tabler": "^0.13.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue": "^6.0.2",
|
||||
"html-docx-js-typescript": "^0.1.5",
|
||||
"less": "^4.4.0",
|
||||
"naive-ui": "^2.41.0",
|
||||
"naive-ui": "^2.43.2",
|
||||
"unplugin-auto-import": "^20.0.0",
|
||||
"unplugin-vue-components": "^29.0.0",
|
||||
"vfonts": "^0.0.3",
|
||||
"vite": "^6.3.5"
|
||||
"vite": "7.2.4"
|
||||
},
|
||||
"keywords": [
|
||||
"AI赋能股票分析",
|
||||
|
||||
@@ -1 +1 @@
|
||||
b0b9f944d9af9c00b6d48234793db58c
|
||||
f4fb0059ba6044c039be717fcc2e40bc
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
|
||||
import {AnalyzeSentimentWithFreqWeight} from "../../wailsjs/go/main/App";
|
||||
import {AnalyzeSentimentWithFreqWeight,GlobalStockIndexes} from "../../wailsjs/go/main/App";
|
||||
import * as echarts from "echarts";
|
||||
import {onMounted,onUnmounted, ref} from "vue";
|
||||
import _ from "lodash";
|
||||
@@ -22,24 +22,60 @@ const { name,darkTheme,kDays ,chartHeight} = defineProps({
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const common = ref([])
|
||||
const america = ref([])
|
||||
const europe = ref([])
|
||||
const asia = ref([])
|
||||
const mainIndex = ref([])
|
||||
const chinaIndex = ref([])
|
||||
const other = ref([])
|
||||
const globalStockIndexes = ref(null)
|
||||
const chartRef = ref(null);
|
||||
const gaugeChartRef = ref(null);
|
||||
const triggerAreas=ref(["main","extra","arrow"])
|
||||
let handleChartInterval=null
|
||||
let handleIndexInterval=null
|
||||
onMounted(() => {
|
||||
handleChart()
|
||||
getIndex()
|
||||
handleChartInterval=setInterval(function () {
|
||||
handleChart()
|
||||
}, 1000 * 60)
|
||||
|
||||
handleIndexInterval=setInterval(function () {
|
||||
getIndex()
|
||||
}, 1000 * 2)
|
||||
})
|
||||
|
||||
onUnmounted(()=>{
|
||||
clearInterval(handleChartInterval)
|
||||
clearInterval(handleIndexInterval)
|
||||
})
|
||||
|
||||
function getIndex() {
|
||||
GlobalStockIndexes().then((res) => {
|
||||
globalStockIndexes.value = res
|
||||
common.value = res["common"]
|
||||
america.value = res["america"]
|
||||
europe.value = res["europe"]
|
||||
asia.value = res["asia"]
|
||||
other.value = res["other"]
|
||||
mainIndex.value=asia.value.filter(function (item) {
|
||||
return ['上海',"深圳","香港","台湾","北京","东京","首尔","纽约","纳斯达克"].includes(item.location)
|
||||
}).concat(america.value.filter(function (item) {
|
||||
return ['上海',"深圳","香港","台湾","北京","东京","首尔","纽约","纳斯达克"].includes(item.location)
|
||||
}))
|
||||
|
||||
chinaIndex.value=asia.value.filter(function (item) {
|
||||
return ['上海',"深圳","香港","台湾","北京"].includes(item.location)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
function handleChart(){
|
||||
const formatUtil = echarts.format;
|
||||
AnalyzeSentimentWithFreqWeight("").then((res) => {
|
||||
console.log(res)
|
||||
//console.log(res)
|
||||
const treemapchart = echarts.init(chartRef.value);
|
||||
const gaugeChart=echarts.init(gaugeChartRef.value);
|
||||
let data = res['frequencies'].map(item => ({
|
||||
@@ -117,7 +153,7 @@ function handleChart(){
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (info) {
|
||||
var value = info.value;
|
||||
var value = info.value.toFixed(2);
|
||||
var frequency = info.data.frequency;
|
||||
var weight = info.data.weight;
|
||||
return [
|
||||
@@ -235,7 +271,7 @@ function handleChart(){
|
||||
data: [
|
||||
{
|
||||
value: res.result.Score*0.2,
|
||||
name: '市场情绪'
|
||||
name: '市场情绪强弱'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -247,14 +283,33 @@ function handleChart(){
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-grid :cols="24" :y-gap="0">
|
||||
<n-gi span="6">
|
||||
<div ref="gaugeChartRef" style="width: 100%;height: auto;--wails-draggable:no-drag" :style="{height:chartHeight+'px'}" ></div>
|
||||
</n-gi>
|
||||
<n-gi span="18">
|
||||
<div ref="chartRef" style="width: 100%;height: auto;--wails-draggable:no-drag" :style="{height:chartHeight+'px'}" ></div>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
<n-collapse :trigger-areas="triggerAreas" :default-expanded-names="['1']" display-directive="show">
|
||||
<n-collapse-item name="1" >
|
||||
<template #header>
|
||||
<n-flex>
|
||||
<n-tag size="small" :bordered="false" v-for="(item, index) in mainIndex" :type="item.zdf>0?'error':'success'">
|
||||
<n-flex>
|
||||
<n-image :width="20" :src="item.img" />
|
||||
<n-text style="font-size: 14px" :type="item.zdf>0?'error':'success'">{{item.name}} {{item.zxj}}</n-text>
|
||||
<n-number-animation :precision="2" :from="0" :to="item.zdf" style="font-size: 14px"/>
|
||||
<n-text style="margin-left: -12px;font-size: 14px" :type="item.zdf>0?'error':'success'">%</n-text>
|
||||
</n-flex>
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
</template>
|
||||
<template #header-extra>
|
||||
主要股指
|
||||
</template>
|
||||
<n-grid :cols="24" :y-gap="0">
|
||||
<n-gi span="6">
|
||||
<div ref="gaugeChartRef" style="width: 100%;height: auto;--wails-draggable:no-drag" :style="{height:chartHeight+'px'}" ></div>
|
||||
</n-gi>
|
||||
<n-gi span="18">
|
||||
<div ref="chartRef" style="width: 100%;height: auto;--wails-draggable:no-drag" :style="{height:chartHeight+'px'}" ></div>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -125,7 +125,12 @@ function Search() {
|
||||
// 计算并设置表格宽度
|
||||
tableScrollX.value = calculateTableWidth(columns.value);
|
||||
} else {
|
||||
message.error(res.msg)
|
||||
if(res.msg){
|
||||
message.error(res.msg)
|
||||
}
|
||||
if(res.message){
|
||||
message.error(res.message)
|
||||
}
|
||||
}
|
||||
}).catch(err => {
|
||||
message.error(err)
|
||||
|
||||
@@ -45,6 +45,7 @@ const panelHeight = ref(window.innerHeight - 240)
|
||||
|
||||
const telegraphList = ref([])
|
||||
const sinaNewsList = ref([])
|
||||
const foreignNewsList = ref([])
|
||||
const common = ref([])
|
||||
const america = ref([])
|
||||
const europe = ref([])
|
||||
@@ -54,6 +55,7 @@ const globalStockIndexes = ref(null)
|
||||
const summaryModal = ref(false)
|
||||
const summaryBTN = ref(true)
|
||||
const darkTheme = ref(false)
|
||||
const httpProxyEnabled = ref(false)
|
||||
const theme = computed(() => {
|
||||
return darkTheme ? 'dark' : 'light'
|
||||
})
|
||||
@@ -96,6 +98,7 @@ onBeforeMount(() => {
|
||||
GetConfig().then(result => {
|
||||
summaryBTN.value = result.openAiEnable
|
||||
darkTheme.value = result.darkTheme
|
||||
httpProxyEnabled.value = result.httpProxyEnabled
|
||||
})
|
||||
GetPromptTemplates("", "").then(res => {
|
||||
promptTemplates.value = res
|
||||
@@ -107,13 +110,15 @@ onBeforeMount(() => {
|
||||
aiConfigs.value = res
|
||||
aiConfigId.value = res[0].ID
|
||||
})
|
||||
|
||||
GetTelegraphList("财联社电报").then((res) => {
|
||||
telegraphList.value = res
|
||||
})
|
||||
GetTelegraphList("新浪财经").then((res) => {
|
||||
sinaNewsList.value = res
|
||||
})
|
||||
GetTelegraphList("外媒").then((res) => {
|
||||
foreignNewsList.value = res
|
||||
})
|
||||
getIndex();
|
||||
industryRank();
|
||||
indexInterval.value = setInterval(() => {
|
||||
@@ -164,6 +169,14 @@ EventsOn("newSinaNews", (data) => {
|
||||
sinaNewsList.value.unshift(...data)
|
||||
}
|
||||
})
|
||||
EventsOn("tradingViewNews", (data) => {
|
||||
if (data!=null) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
foreignNewsList.value.pop()
|
||||
}
|
||||
foreignNewsList.value.unshift(...data)
|
||||
}
|
||||
})
|
||||
|
||||
//获取页面高度
|
||||
window.onresize = () => {
|
||||
@@ -324,6 +337,9 @@ function ReFlesh(source) {
|
||||
if (source === "新浪财经") {
|
||||
sinaNewsList.value = res
|
||||
}
|
||||
if (source === "外媒") {
|
||||
foreignNewsList.value = res
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -337,13 +353,17 @@ function ReFlesh(source) {
|
||||
<AnalyzeMartket :dark-theme="darkTheme" :chart-height="300" :kDays="1" :name="'最近24小时热词'" />
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-grid :cols="2" :y-gap="0">
|
||||
<n-grid :cols="httpProxyEnabled?3:2" :y-gap="0">
|
||||
<n-gi>
|
||||
<news-list :newsList="telegraphList" :header-title="'财联社电报'" @update:message="ReFlesh"></news-list>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<news-list :newsList="sinaNewsList" :header-title="'新浪财经'" @update:message="ReFlesh"></news-list>
|
||||
</n-gi>
|
||||
<n-gi v-if="httpProxyEnabled">
|
||||
<news-list :newsList="foreignNewsList" :header-title="'外媒'" @update:message="ReFlesh"></news-list>
|
||||
</n-gi>
|
||||
|
||||
</n-grid>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
|
||||
@@ -29,11 +29,19 @@ const updateMessage = () => {
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-list-item v-for="item in newsList">
|
||||
<n-space justify="start">
|
||||
<n-space justify="start" >
|
||||
<n-text justify="start" :bordered="false" :type="item.isRed?'error':'info'">
|
||||
<n-tag size="small" :type="item.isRed?'error':'warning'" :bordered="false"> {{ item.time }}</n-tag>
|
||||
{{ item.content }}
|
||||
<n-gradient-text :size="14" :type="'warning'" :bordered="false">{{ item.title }}</n-gradient-text> <n-text :type="item.isRed?'error':'info'">{{ item.content }}</n-text>
|
||||
</n-text>
|
||||
<!-- <n-collapse v-if="item.title">-->
|
||||
<!-- <n-collapse-item :title="item.title" :name="item.title">-->
|
||||
<!-- <n-text justify="start" :bordered="false" :type="item.isRed?'error':'info'">-->
|
||||
<!-- <n-tag size="small" :type="item.isRed?'error':'warning'" :bordered="false"> {{ item.time }}</n-tag>-->
|
||||
<!-- {{ item.content }}-->
|
||||
<!-- </n-text>-->
|
||||
<!-- </n-collapse-item>-->
|
||||
<!-- </n-collapse>-->
|
||||
</n-space>
|
||||
<n-space v-if="item.subjects" style="margin-top: 2px">
|
||||
<n-tag :bordered="false" type="success" size="small" v-for="sub in item.subjects">
|
||||
|
||||
@@ -46,6 +46,7 @@ const formValue = ref({
|
||||
httpProxy:"",
|
||||
httpProxyEnabled:false,
|
||||
enableAgent: false,
|
||||
qgqpBId: '',
|
||||
})
|
||||
|
||||
// 添加一个新的AI配置到列表
|
||||
@@ -105,6 +106,7 @@ onMounted(() => {
|
||||
formValue.value.httpProxy=res.httpProxy;
|
||||
formValue.value.httpProxyEnabled=res.httpProxyEnabled;
|
||||
formValue.value.enableAgent = res.enableAgent;
|
||||
formValue.value.qgqpBId = res.qgqpBId;
|
||||
|
||||
})
|
||||
|
||||
@@ -145,6 +147,7 @@ function saveConfig() {
|
||||
httpProxy:formValue.value.httpProxy,
|
||||
httpProxyEnabled:formValue.value.httpProxyEnabled,
|
||||
enableAgent: formValue.value.enableAgent,
|
||||
qgqpBId: formValue.value.qgqpBId
|
||||
})
|
||||
|
||||
if (config.sponsorCode) {
|
||||
@@ -235,6 +238,7 @@ function importConfig() {
|
||||
formValue.value.httpProxy=config.httpProxy
|
||||
formValue.value.httpProxyEnabled=config.httpProxyEnabled
|
||||
formValue.value.enableAgent = config.enableAgent
|
||||
formValue.value.qgqpBId = config.qgqpBId
|
||||
};
|
||||
reader.readAsText(file);
|
||||
};
|
||||
@@ -328,6 +332,9 @@ function deletePrompt(ID) {
|
||||
<n-form-item-gi :span="3" label="AI智能体:" path="enableAgent">
|
||||
<n-switch v-model:value="formValue.enableAgent"/>
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="11" label="东财唯一标识:" path="qgqpBId">
|
||||
<n-input type="text" placeholder="东财唯一标识" v-model:value="formValue.qgqpBId" clearable/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<n-form-item-gi :span="11" label="赞助码:" path="sponsorCode">
|
||||
<n-input-group>
|
||||
|
||||
@@ -394,6 +394,7 @@ export namespace data {
|
||||
httpProxy: string;
|
||||
httpProxyEnabled: boolean;
|
||||
enableAgent: boolean;
|
||||
qgqpBId: string;
|
||||
aiConfigs: AIConfig[];
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
@@ -430,6 +431,7 @@ export namespace data {
|
||||
this.httpProxy = source["httpProxy"];
|
||||
this.httpProxyEnabled = source["httpProxyEnabled"];
|
||||
this.enableAgent = source["enableAgent"];
|
||||
this.qgqpBId = source["qgqpBId"];
|
||||
this.aiConfigs = this.convertValues(source["aiConfigs"], AIConfig);
|
||||
}
|
||||
|
||||
|
||||
8
go.mod
8
go.mod
@@ -25,9 +25,9 @@ require (
|
||||
github.com/tidwall/gjson v1.14.4
|
||||
github.com/wailsapp/wails/v2 v2.10.1
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/net v0.38.0
|
||||
golang.org/x/sys v0.36.0
|
||||
golang.org/x/text v0.26.0
|
||||
golang.org/x/net v0.47.0
|
||||
golang.org/x/sys v0.38.0
|
||||
golang.org/x/text v0.31.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gorm.io/gorm v1.25.12
|
||||
gorm.io/plugin/dbresolver v1.5.3
|
||||
@@ -119,7 +119,7 @@ require (
|
||||
github.com/yargevad/filepathx v1.0.0 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
20
go.sum
20
go.sum
@@ -350,8 +350,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.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
|
||||
@@ -378,8 +378,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.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.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -411,8 +411,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.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.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -422,8 +422,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -434,8 +434,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.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.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
||||
Reference in New Issue
Block a user