diff --git a/README.md b/README.md
index 01a7761..6132167 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@
| 不再强制依赖Chrome浏览器 | ✅ | 默认使用edge浏览器抓取新闻资讯 |
## 👀 更新日志
+### 2025.05.08 添加A股盘口数据解析和展示功能
### 2025.05.07 优化分时图的展示
### 2025.04.29 补全港股/美股基础数据,优化港股股价延迟问题,优化初始化逻辑
### 2025.04.25 市场资讯支持AI分析和总结:让AI帮你读市场!
diff --git a/backend/data/stock_data_api.go b/backend/data/stock_data_api.go
index d4a134a..4399358 100644
--- a/backend/data/stock_data_api.go
+++ b/backend/data/stock_data_api.go
@@ -295,12 +295,16 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCodes ...string) (*[]
stockInfos := make([]StockInfo, 0)
hkcodes := slice.Filter(StockCodes, func(i int, s string) bool {
- return strutil.HasPrefixAny(s, []string{"hk", "HK"})
+ return strutil.HasPrefixAny(s, []string{"hk", "HK", "sh", "sz"})
})
if hkcodes != nil && len(hkcodes) > 0 {
hkcodesStr := slice.JoinFunc(hkcodes, ",", func(s string) string {
- return "r_" + strings.ToLower(s)
+ if strutil.HasPrefixAny(s, []string{"hk", "HK"}) {
+ return "r_" + strings.ToLower(s)
+ } else {
+ return strings.ToLower(s)
+ }
})
url := fmt.Sprintf(txStockUrl, time.Now().Unix(), hkcodesStr)
resp, err := receiver.client.R().
@@ -336,7 +340,7 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCodes ...string) (*[]
}
szzsusCodes := slice.Filter(StockCodes, func(i int, s string) bool {
- return !strutil.HasPrefixAny(s, []string{"hk", "HK"})
+ return !strutil.HasPrefixAny(s, []string{"hk", "HK", "sh", "sz"})
})
codes := slice.JoinFunc(szzsusCodes, ",", func(s string) string {
@@ -556,13 +560,16 @@ func GB18030ToUTF8(bs []byte) string {
func ParseTxStockData(data string) (*StockInfo, error) {
//v_r_hk09660="100~地平线机器人-W~09660~6.240~5.690~5.800~192659034.0~0~0~6.240~0~0~0~0~0~0~0~0~0~6.240~0~0~0~0~0~0~0~0~0~192659034.0~2025/04/29
//13:41:04~0.550~9.67~6.450~5.710~6.240~192659034.0~1180471843.140~0~32.51~~0~0~13.01~691.1364~823.6983~HORIZONROBOT-W~0.00~10.380~3.320~1.07~-16.03~0~0~0~0~0~32.51~6.40~1.74~600~73.33~17.96~GP~19.70~11.51~-0.95~-18.54~44.44~13200293682.00~11075904412.00~32.51~0.000~6.127~56.39~HKD~1~30";
+ //v_sz002241="51~歌尔股份~002241~22.26~22.27~0.00~0~0~0~22.26~1004~0.00~0~0.00~0~0.00~0~0.00~0~22.26~1004~0.00~558~0.00~0~0.00~0~0.00~0~~20250509092233~-0.01~-0.04~0.00~0.00~22.26/0/0~0~0~0.00~28.21~~0.00~0.00~0.00~686.46~777.09~2.31~24.50~20.04~0.00~-558~0.00~41.44~29.16~~~1.24~0.0000~0.0000~0~
+ //~GP-A~-13.75~6.76~1.09~8.18~3.39~30.63~15.70~6.87~17.47~-23.95~3083811231~3490989083~-21.75~12.02~3083811231~~~39.36~-0.04~~CNY~0~~0.00~0";
+
datas := strutil.SplitAndTrim(data, "=", "\"")
if len(datas) < 2 {
return nil, fmt.Errorf("invalid data format")
}
var result map[string]string
var err error
- if strutil.ContainsAny(datas[0], []string{"v_r_hk", "v_hk"}) {
+ if strutil.ContainsAny(datas[0], []string{"v_r_hk", "v_hk", "v_sz", "v_sh"}) {
result, err = ParseTxHKStockData(datas)
}
@@ -640,12 +647,50 @@ func ParseTxHKStockData(datas []string) (map[string]string, error) {
result["今日最高价"] = parts[33]
result["今日最低价"] = parts[34]
- timestr := strutil.ReplaceWithMap(parts[30], map[string]string{
- "/": "-",
- })
+
+ if strutil.HasPrefixAny(stockCode, []string{"sz", "sh"}) {
+ result["买一报价"] = parts[9]
+ result["买一申报"] = parts[10]
+ result["买二报价"] = parts[11]
+ result["买二申报"] = parts[12]
+ result["买三报价"] = parts[13]
+ result["买三申报"] = parts[14]
+ result["买四报价"] = parts[15]
+ result["买四申报"] = parts[16]
+ result["买五报价"] = parts[17]
+ result["买五申报"] = parts[18]
+
+ result["卖一报价"] = parts[19]
+ result["卖一申报"] = parts[20]
+ result["卖二报价"] = parts[21]
+ result["卖二申报"] = parts[22]
+ result["卖三报价"] = parts[23]
+ result["卖三申报"] = parts[24]
+ result["卖四报价"] = parts[25]
+ result["卖四申报"] = parts[26]
+ result["卖五报价"] = parts[27]
+ result["卖五申报"] = parts[28]
+
+ }
+
+ timestr := ""
+
+ if strutil.ContainsAny(parts[30], []string{"/"}) {
+ timestr = strutil.ReplaceWithMap(parts[30], map[string]string{
+ "/": "-",
+ "\n": " ",
+ })
+ result["日期"] = strutil.SplitAndTrim(timestr, " ", "")[0]
+ result["时间"] = strutil.SplitAndTrim(timestr, " ", "")[1]
+ } else {
+ result["日期"] = strutil.Trim(parts[29])[0:4] + "-" + strutil.Trim(parts[29])[4:6] + "-" + strutil.Trim(parts[29])[6:8]
+ result["时间"] = strutil.Trim(parts[29])[8:10] + ":" + strutil.Trim(parts[29])[10:12] + ":" + strutil.Trim(parts[29])[12:14]
+ result["今日最高价"] = parts[32]
+ result["今日最低价"] = parts[33]
+ }
+ //logger.SugaredLogger.Infof("股票数据解析完成 %s %s 时间: %s,%s", parts[1], parts[3], parts[29], parts[30])
+
//logger.SugaredLogger.Infof("股票数据解析完成 时间: %v", timestr)
- result["日期"] = strutil.SplitAndTrim(timestr, " ", "")[0]
- result["时间"] = strutil.SplitAndTrim(timestr, " ", "")[1]
//logger.SugaredLogger.Infof("股票数据解析完成: %v", result)
diff --git a/backend/data/stock_data_api_test.go b/backend/data/stock_data_api_test.go
index 45c0303..483b395 100644
--- a/backend/data/stock_data_api_test.go
+++ b/backend/data/stock_data_api_test.go
@@ -116,6 +116,9 @@ func TestGetHKStockInfo(t *testing.T) {
func TestParseTxStockData(t *testing.T) {
str := "v_r_hk09660=\"100~地平线机器人-W~09660~6.340~5.690~5.800~210980204.0~0~0~6.340~0~0~0~0~0~0~0~0~0~6.340~0~0~0~0~0~0~0~0~0~210980204.0~2025/04/29\n14:14:52~0.650~11.42~6.450~5.710~6.340~210980204.0~1295585259.040~0~33.03~~0~0~13.01~702.2123~836.8986~HORIZONROBOT-W~0.00~10.380~3.320~1.00~-53.74~0~0~0~0~0~33.03~6.50~1.90~600~76.11~19.85~GP~19.70~11.51~0.63~-17.23~46.76~13200293682.00~11075904412.00~33.03~0.000~6.141~58.90~HKD~1~30\";"
+ //str = "v_sz002241=\"51~歌尔股份~002241~22.26~22.27~0.00~0~0~0~22.26~1004~0.00~0~0.00~0~0.00~0~0.00~0~22.26~1004~0.00~558~0.00~0~0.00~0~0.00~0~~20250509092233~-0.01~-0.04~0.00~0.00~22.26/0/0~0~0~0.00~28.21~~0.00~0.00~0.00~686.46~777.09~2.31~24.50~20.04~0.00~-558~0.00~41.44~29.16~~~1.24~0.0000~0.0000~0~\n~GP-A~-13.75~6.76~1.09~8.18~3.39~30.63~15.70~6.87~17.47~-23.95~3083811231~3490989083~-21.75~12.02~3083811231~~~39.36~-0.04~~CNY~0~~0.00~0\";"
+ str = "v_sz002241=\"51~歌尔股份~002241~21.92~22.27~22.14~109872~40211~69642~21.91~25~21.90~961~21.89~257~21.88~748~21.87~665~21.92~86~21.93~168~21.94~556~21.95~171~21.96~85~~20250509094209~-0.35~-1.57~22.16~21.84~21.92/109872/241183171~109872~24118~0.36~27.78~~22.16~21.84~1.44~675.97~765.22~2.27~24.50~20.04~2.57~1590~21.95~40.80~28.71~~~1.24~24118.3171~0.0000~0~\n~GP-A~-15.07~5.13~1.11~8.18~3.39~30.63~15.70~5.23~15.67~-25.11~3083811231~3490989083~42.72~10.31~3083811231~~~37.23~0.18~~CNY~0~~21.85~1952\";"
+ //str = "v_r_hk09660=\"100~地平线机器人-W~09660~6.860~7.000~7.010~21157200.0~0~0~6.860~0~0~0~0~0~0~0~0~0~6.860~0~0~0~0~0~0~0~0~0~21157200.0~2025/05/09\n09:43:13~-0.140~-2.00~7.030~6.730~6.860~21157200.0~144331073.000~0~35.74~~0~0~4.29~759.8070~905.5401~HORIZONROBOT-W~0.00~10.380~3.320~2.93~11.10~0~0~0~0~0~35.74~7.04~0.19~600~90.56~4.73~GP~19.70~11.51~17.26~48.48~13.58~13200293682.00~11075904412.00~35.74~0.000~6.822~71.93~HKD~1~30\";"
info, _ := ParseTxStockData(str)
logger.SugaredLogger.Infof("%+#v", info)
}
diff --git a/frontend/src/components/stock.vue b/frontend/src/components/stock.vue
index fd0c4f3..49b0918 100644
--- a/frontend/src/components/stock.vue
+++ b/frontend/src/components/stock.vue
@@ -632,7 +632,7 @@ function showFsChart(code, name) {
let option = {
title: {
- subtext: "["+result.date+"] 开盘:"+openprice+" 收盘:"+closeprice+" 最高:"+max+" 最低:"+min,
+ subtext: "["+result.date+"] 开盘:"+openprice+" 最新:"+closeprice+" 最高:"+max+" 最低:"+min,
left: 'center',
top: '10',
textStyle: {
@@ -1585,6 +1585,52 @@ function delStockGroup(code,name,groupId){
{{"今开 "+result["今日开盘价"]}}
+
+
+
+
+ {{"买一 "+result["买一报价"]+'('+result["买一申报"]+")"}}
+ {{"卖一 "+result["卖一报价"]+'('+result["卖一申报"]+")"}}
+
+
+
+
+ {{"买一 "+result["买一报价"]+'('+result["买一申报"]+")"}}
+
+
+ {{"卖一 "+result["卖一报价"]+'('+result["卖一申报"]+")"}}
+
+
+
+ {{"买二 "+result["买二报价"]+'('+result["买二申报"]+")"}}
+
+
+ {{"卖二 "+result["卖二报价"]+'('+result["卖二申报"]+")"}}
+
+
+
+ {{"买三 "+result["买三报价"]+'('+result["买三申报"]+")"}}
+
+
+ {{"买三 "+result["卖三报价"]+'('+result["卖三申报"]+")"}}
+
+
+
+ {{"买四 "+result["买四报价"]+'('+result["买四申报"]+")"}}
+
+
+ {{"卖四 "+result["卖四报价"]+'('+result["卖四申报"]+")"}}
+
+
+
+ {{"买五 "+result["买五报价"]+'('+result["买五申报"]+")"}}
+
+
+ {{"卖五 "+result["卖五报价"]+'('+result["卖五申报"]+")"}}
+
+
+
+
{{result['股票代码']}}
@@ -1650,6 +1696,52 @@ function delStockGroup(code,name,groupId){
{{"今开 "+result["今日开盘价"]}}
+
+
+
+
+ {{"买一 "+result["买一报价"]+'('+result["买一申报"]+")"}}
+ {{"卖一 "+result["卖一报价"]+'('+result["卖一申报"]+")"}}
+
+
+
+
+ {{"买一 "+result["买一报价"]+'('+result["买一申报"]+")"}}
+
+
+ {{"卖一 "+result["卖一报价"]+'('+result["卖一申报"]+")"}}
+
+
+
+ {{"买二 "+result["买二报价"]+'('+result["买二申报"]+")"}}
+
+
+ {{"卖二 "+result["卖二报价"]+'('+result["卖二申报"]+")"}}
+
+
+
+ {{"买三 "+result["买三报价"]+'('+result["买三申报"]+")"}}
+
+
+ {{"买三 "+result["卖三报价"]+'('+result["卖三申报"]+")"}}
+
+
+
+ {{"买四 "+result["买四报价"]+'('+result["买四申报"]+")"}}
+
+
+ {{"卖四 "+result["卖四报价"]+'('+result["卖四申报"]+")"}}
+
+
+
+ {{"买五 "+result["买五报价"]+'('+result["买五申报"]+")"}}
+
+
+ {{"卖五 "+result["卖五报价"]+'('+result["卖五申报"]+")"}}
+
+
+
+
{{result['股票代码']}}
diff --git a/main.go b/main.go
index 4808225..2f30eac 100644
--- a/main.go
+++ b/main.go
@@ -55,22 +55,7 @@ var VersionCommit string
func main() {
checkDir("data")
db.Init("")
- db.Dao.AutoMigrate(&data.StockInfo{})
- db.Dao.AutoMigrate(&data.StockBasic{})
- db.Dao.AutoMigrate(&data.FollowedStock{})
- db.Dao.AutoMigrate(&data.IndexBasic{})
- db.Dao.AutoMigrate(&data.Settings{})
- db.Dao.AutoMigrate(&models.AIResponseResult{})
- db.Dao.AutoMigrate(&models.StockInfoHK{})
- db.Dao.AutoMigrate(&models.StockInfoUS{})
- db.Dao.AutoMigrate(&data.FollowedFund{})
- db.Dao.AutoMigrate(&data.FundBasic{})
- db.Dao.AutoMigrate(&models.PromptTemplate{})
- db.Dao.AutoMigrate(&data.Group{})
- db.Dao.AutoMigrate(&data.GroupStock{})
- db.Dao.AutoMigrate(&models.Tags{})
- db.Dao.AutoMigrate(&models.Telegraph{})
- db.Dao.AutoMigrate(&models.TelegraphTags{})
+ go AutoMigrate()
//db.Dao.Model(&data.Group{}).Where("id = ?", 0).FirstOrCreate(&data.Group{
// Name: "默认分组",
@@ -214,6 +199,25 @@ func main() {
}
+func AutoMigrate() {
+ db.Dao.AutoMigrate(&data.StockInfo{})
+ db.Dao.AutoMigrate(&data.StockBasic{})
+ db.Dao.AutoMigrate(&data.FollowedStock{})
+ db.Dao.AutoMigrate(&data.IndexBasic{})
+ db.Dao.AutoMigrate(&data.Settings{})
+ db.Dao.AutoMigrate(&models.AIResponseResult{})
+ db.Dao.AutoMigrate(&models.StockInfoHK{})
+ db.Dao.AutoMigrate(&models.StockInfoUS{})
+ db.Dao.AutoMigrate(&data.FollowedFund{})
+ db.Dao.AutoMigrate(&data.FundBasic{})
+ db.Dao.AutoMigrate(&models.PromptTemplate{})
+ db.Dao.AutoMigrate(&data.Group{})
+ db.Dao.AutoMigrate(&data.GroupStock{})
+ db.Dao.AutoMigrate(&models.Tags{})
+ db.Dao.AutoMigrate(&models.Telegraph{})
+ db.Dao.AutoMigrate(&models.TelegraphTags{})
+}
+
func initStockDataUS() {
var v []models.StockInfoUS
err := json.Unmarshal(stocksBinUS, &v)