From 7e24424ea0288f185e7f61e9a967f915d615a599 Mon Sep 17 00:00:00 2001 From: ArvinLovegood Date: Fri, 9 May 2025 11:44:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(stock):=E6=B7=BB=E5=8A=A0A=E8=82=A1?= =?UTF-8?q?=E7=9B=98=E5=8F=A3=E6=95=B0=E6=8D=AE=E8=A7=A3=E6=9E=90=E5=92=8C?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 stock.vue 中添加盘口数据展示组件 - 在 stock_data_api.go 中增加 A 股盘口数据解析逻辑 - 优化数据库自动迁移逻辑,提取到单独的函数中 - 更新测试用例以覆盖新的盘口数据解析功能 --- README.md | 1 + backend/data/stock_data_api.go | 63 ++++++++++++++++--- backend/data/stock_data_api_test.go | 3 + frontend/src/components/stock.vue | 94 ++++++++++++++++++++++++++++- main.go | 36 ++++++----- 5 files changed, 171 insertions(+), 26 deletions(-) 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["卖五申报"]+")"}} + + + +