mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
refactor(frontend):重构前端关注列表和美股股票价格更新逻辑
(当前美股功能处于 测试阶段,可能不稳定。) - 修改 GetFollowList 接口返回类型为 any - 优化关注列表中美国股票代码处理逻辑 - 增加股票价格更新时的盘前盘后信息 - 调整股票数据解析和处理逻辑
This commit is contained in:
parent
826a29cd8c
commit
ce91b2e532
23
app.go
23
app.go
@ -279,15 +279,16 @@ func MonitorStockPrices(a *App) {
|
|||||||
if strutil.HasPrefixAny(stockInfo.Code, []string{"hk", "HK"}) && (!IsHKTradingTime(time.Now())) {
|
if strutil.HasPrefixAny(stockInfo.Code, []string{"hk", "HK"}) && (!IsHKTradingTime(time.Now())) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strutil.HasPrefixAny(stockInfo.Code, []string{"us", "US", "gb_"}) && (!IsUSTradingTime(time.Now())) {
|
//if strutil.HasPrefixAny(stockInfo.Code, []string{"us", "US", "gb_"}) && (!IsUSTradingTime(time.Now())) {
|
||||||
continue
|
// continue
|
||||||
}
|
//}
|
||||||
|
|
||||||
total += stockInfo.ProfitAmountToday
|
//total += stockInfo.ProfitAmountToday
|
||||||
price, _ := convertor.ToFloat(stockInfo.Price)
|
//price, _ := convertor.ToFloat(stockInfo.Price)
|
||||||
if stockInfo.PrePrice != price {
|
//if stockInfo.PrePrice != price {
|
||||||
go runtime.EventsEmit(a.ctx, "stock_price", stockInfo)
|
logger.SugaredLogger.Infof("-----------------------股票代码: %s, 股票名称: %s, 股票价格: %s,盘前盘后:%s", stockInfo.Code, stockInfo.Name, stockInfo.Price, stockInfo.BA)
|
||||||
}
|
go runtime.EventsEmit(a.ctx, "stock_price", stockInfo)
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
if total != 0 {
|
if total != 0 {
|
||||||
title := "go-stock " + time.Now().Format(time.DateTime) + fmt.Sprintf(" %.2f¥", total)
|
title := "go-stock " + time.Now().Format(time.DateTime) + fmt.Sprintf(" %.2f¥", total)
|
||||||
@ -307,6 +308,10 @@ func GetStockInfos(follows ...data.FollowedStock) *[]data.StockInfo {
|
|||||||
stockData, _ := data.NewStockDataApi().GetStockCodeRealTimeData(stockCodes...)
|
stockData, _ := data.NewStockDataApi().GetStockCodeRealTimeData(stockCodes...)
|
||||||
for _, info := range *stockData {
|
for _, info := range *stockData {
|
||||||
v, ok := slice.FindBy(follows, func(idx int, follow data.FollowedStock) bool {
|
v, ok := slice.FindBy(follows, func(idx int, follow data.FollowedStock) bool {
|
||||||
|
if strutil.HasPrefixAny(follow.StockCode, []string{"US", "us"}) {
|
||||||
|
return strings.ToLower(strings.Replace(follow.StockCode, "us", "gb_", 1)) == info.Code
|
||||||
|
}
|
||||||
|
|
||||||
return follow.StockCode == info.Code
|
return follow.StockCode == info.Code
|
||||||
})
|
})
|
||||||
if ok {
|
if ok {
|
||||||
@ -453,7 +458,7 @@ func (a *App) UnFollow(stockCode string) string {
|
|||||||
return data.NewStockDataApi().UnFollow(stockCode)
|
return data.NewStockDataApi().UnFollow(stockCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetFollowList() []data.FollowedStock {
|
func (a *App) GetFollowList() *[]data.FollowedStock {
|
||||||
return data.NewStockDataApi().GetFollowList()
|
return data.NewStockDataApi().GetFollowList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,8 @@ type StockInfo struct {
|
|||||||
A4V string `json:"卖四申报"`
|
A4V string `json:"卖四申报"`
|
||||||
A5P string `json:"卖五报价"`
|
A5P string `json:"卖五报价"`
|
||||||
A5V string `json:"卖五申报"`
|
A5V string `json:"卖五申报"`
|
||||||
|
Market string `json:"市场"`
|
||||||
|
BA string `json:"盘前盘后"`
|
||||||
|
|
||||||
//以下是字段值需二次计算
|
//以下是字段值需二次计算
|
||||||
ChangePercent float64 `json:"changePercent"` //涨跌幅
|
ChangePercent float64 `json:"changePercent"` //涨跌幅
|
||||||
@ -315,6 +317,7 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCodes ...string) (*[]
|
|||||||
for _, data := range dataStr {
|
for _, data := range dataStr {
|
||||||
//logger.SugaredLogger.Info(data)
|
//logger.SugaredLogger.Info(data)
|
||||||
stockData, err := ParseFullSingleStockData(data)
|
stockData, err := ParseFullSingleStockData(data)
|
||||||
|
logger.SugaredLogger.Infof("GetStockCodeRealTimeData %v", stockData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.SugaredLogger.Error(err.Error())
|
logger.SugaredLogger.Error(err.Error())
|
||||||
continue
|
continue
|
||||||
@ -360,11 +363,21 @@ func (receiver StockDataApi) Follow(stockCode string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) UnFollow(stockCode string) string {
|
func (receiver StockDataApi) UnFollow(stockCode string) string {
|
||||||
|
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||||
|
stockCode = strings.ToUpper(stockCode)
|
||||||
|
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||||
|
stockCode = strings.Replace(stockCode, "GB_", "us", 1)
|
||||||
|
}
|
||||||
db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Delete(&FollowedStock{})
|
db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Delete(&FollowedStock{})
|
||||||
return "取消关注成功"
|
return "取消关注成功"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) SetCostPriceAndVolume(price float64, volume int64, stockCode string) string {
|
func (receiver StockDataApi) SetCostPriceAndVolume(price float64, volume int64, stockCode string) string {
|
||||||
|
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||||
|
stockCode = strings.ToUpper(stockCode)
|
||||||
|
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||||
|
stockCode = strings.Replace(stockCode, "GB_", "us", 1)
|
||||||
|
}
|
||||||
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Update("cost_price", price).Update("volume", volume).Error
|
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Update("cost_price", price).Update("volume", volume).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.SugaredLogger.Error(err.Error())
|
logger.SugaredLogger.Error(err.Error())
|
||||||
@ -374,6 +387,11 @@ func (receiver StockDataApi) SetCostPriceAndVolume(price float64, volume int64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) SetAlarmChangePercent(val, alarmPrice float64, stockCode string) string {
|
func (receiver StockDataApi) SetAlarmChangePercent(val, alarmPrice float64, stockCode string) string {
|
||||||
|
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||||
|
stockCode = strings.ToUpper(stockCode)
|
||||||
|
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||||
|
stockCode = strings.Replace(stockCode, "GB_", "us", 1)
|
||||||
|
}
|
||||||
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Updates(&map[string]any{
|
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Updates(&map[string]any{
|
||||||
"alarm_change_percent": val,
|
"alarm_change_percent": val,
|
||||||
"alarm_price": alarmPrice,
|
"alarm_price": alarmPrice,
|
||||||
@ -386,11 +404,16 @@ func (receiver StockDataApi) SetAlarmChangePercent(val, alarmPrice float64, stoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) SetStockSort(sort int64, stockCode string) {
|
func (receiver StockDataApi) SetStockSort(sort int64, stockCode string) {
|
||||||
|
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||||
|
stockCode = strings.ToUpper(stockCode)
|
||||||
|
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||||
|
stockCode = strings.Replace(stockCode, "GB_", "us", 1)
|
||||||
|
}
|
||||||
db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Update("sort", sort)
|
db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Update("sort", sort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) GetFollowList() []FollowedStock {
|
func (receiver StockDataApi) GetFollowList() *[]FollowedStock {
|
||||||
var result []FollowedStock
|
var result *[]FollowedStock
|
||||||
db.Dao.Model(&FollowedStock{}).Order("sort asc,time desc").Find(&result)
|
db.Dao.Model(&FollowedStock{}).Order("sort asc,time desc").Find(&result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -427,7 +450,7 @@ func (receiver StockDataApi) GetStockList(key string) []StockBasic {
|
|||||||
}
|
}
|
||||||
for _, item := range result4 {
|
for _, item := range result4 {
|
||||||
result = append(result, StockBasic{
|
result = append(result, StockBasic{
|
||||||
TsCode: item.Code,
|
TsCode: strings.ToLower(strings.Replace(item.Code, "us", "gb_", 1)),
|
||||||
Name: item.Name,
|
Name: item.Name,
|
||||||
Fullname: item.Name,
|
Fullname: item.Name,
|
||||||
Market: "US",
|
Market: "US",
|
||||||
@ -469,9 +492,11 @@ func ParseFullSingleStockData(data string) (*StockInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
logger.SugaredLogger.Infof("股票数据解析完成marshal: %s", marshal)
|
||||||
stockInfo := &StockInfo{}
|
stockInfo := &StockInfo{}
|
||||||
err = json.Unmarshal(marshal, &stockInfo)
|
err = json.Unmarshal(marshal, &stockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.SugaredLogger.Errorf("json.Unmarshal error:%s", err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//logger.SugaredLogger.Infof("股票数据解析完成stockInfo: %+v", stockInfo)
|
//logger.SugaredLogger.Infof("股票数据解析完成stockInfo: %+v", stockInfo)
|
||||||
@ -509,7 +534,7 @@ func ParseUSStockData(datas []string) (map[string]string, error) {
|
|||||||
0.00, 18
|
0.00, 18
|
||||||
12190000000, 19
|
12190000000, 19
|
||||||
71, 20
|
71, 20
|
||||||
170.2000, 21 盘后
|
170.2000, 21 盘前盘后盘
|
||||||
-0.01, 22
|
-0.01, 22
|
||||||
-0.01, 23
|
-0.01, 23
|
||||||
Feb 27 07:59PM EST, 24
|
Feb 27 07:59PM EST, 24
|
||||||
@ -532,9 +557,10 @@ func ParseUSStockData(datas []string) (map[string]string, error) {
|
|||||||
result["今日最高价"] = parts[6]
|
result["今日最高价"] = parts[6]
|
||||||
result["今日最低价"] = parts[7]
|
result["今日最低价"] = parts[7]
|
||||||
result["当前价格"] = parts[1]
|
result["当前价格"] = parts[1]
|
||||||
|
result["盘前盘后"] = parts[21]
|
||||||
result["日期"] = strutil.SplitAndTrim(parts[3], " ", "")[0]
|
result["日期"] = strutil.SplitAndTrim(parts[3], " ", "")[0]
|
||||||
result["时间"] = strutil.SplitAndTrim(parts[3], " ", "")[1]
|
result["时间"] = strutil.SplitAndTrim(parts[3], " ", "")[1]
|
||||||
//logger.SugaredLogger.Infof("美股股票数据解析完成: %v", result)
|
logger.SugaredLogger.Infof("美股股票数据解析完成: %v", result)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,11 @@ onBeforeMount(()=>{
|
|||||||
GetFollowList().then(result => {
|
GetFollowList().then(result => {
|
||||||
followList.value = result
|
followList.value = result
|
||||||
for (const followedStock of 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)) {
|
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||||
|
console.log("followList",followedStock.StockCode)
|
||||||
stocks.value.push(followedStock.StockCode)
|
stocks.value.push(followedStock.StockCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +196,6 @@ EventsOn("showSearch",(data)=>{
|
|||||||
})
|
})
|
||||||
|
|
||||||
EventsOn("stock_price",(data)=>{
|
EventsOn("stock_price",(data)=>{
|
||||||
//console.log("stock_price",data['股票代码'])
|
|
||||||
updateData(data)
|
updateData(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -390,6 +393,8 @@ function getStockList(value){
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function updateData(result) {
|
async function updateData(result) {
|
||||||
|
console.log("stock_price",result['日期'],result['时间'],result['股票代码'],result['股票名称'],result['当前价格'],result['盘前盘后'])
|
||||||
|
|
||||||
if(result["当前价格"]<=0){
|
if(result["当前价格"]<=0){
|
||||||
result["当前价格"]=result["卖一报价"]
|
result["当前价格"]=result["卖一报价"]
|
||||||
}
|
}
|
||||||
@ -474,7 +479,7 @@ function setStock(code,name){
|
|||||||
//console.log("res:",res)
|
//console.log("res:",res)
|
||||||
formModel.value.name=name
|
formModel.value.name=name
|
||||||
formModel.value.code=code
|
formModel.value.code=code
|
||||||
formModel.value.volume=res[0].Volume
|
formModel.value.volume=res[0].Volume?res[0].Volume:0
|
||||||
formModel.value.costPrice=res[0].CostPrice
|
formModel.value.costPrice=res[0].CostPrice
|
||||||
formModel.value.alarm=res[0].AlarmChangePercent
|
formModel.value.alarm=res[0].AlarmChangePercent
|
||||||
formModel.value.alarmPrice=res[0].AlarmPrice
|
formModel.value.alarmPrice=res[0].AlarmPrice
|
||||||
@ -759,6 +764,7 @@ AI赋能股票分析:自选股行情获取,成本盈亏展示,涨跌报警
|
|||||||
<n-gi>
|
<n-gi>
|
||||||
<n-text :type="result.type" >
|
<n-text :type="result.type" >
|
||||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']" :to="Number(result['当前价格'])" />
|
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']" :to="Number(result['当前价格'])" />
|
||||||
|
<n-tag size="small" :bordered="false" v-if="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" />%
|
||||||
@ -783,6 +789,7 @@ AI赋能股票分析:自选股行情获取,成本盈亏展示,涨跌报警
|
|||||||
</n-gi>
|
</n-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
<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" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
<n-button size="tiny" secondary type="primary" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||||
取消关注
|
取消关注
|
||||||
|
2
frontend/wailsjs/go/main/App.d.ts
vendored
2
frontend/wailsjs/go/main/App.d.ts
vendored
@ -13,7 +13,7 @@ export function GetAIResponseResult(arg1:string):Promise<models.AIResponseResult
|
|||||||
|
|
||||||
export function GetConfig():Promise<data.Settings>;
|
export function GetConfig():Promise<data.Settings>;
|
||||||
|
|
||||||
export function GetFollowList():Promise<Array<data.FollowedStock>>;
|
export function GetFollowList():Promise<any>;
|
||||||
|
|
||||||
export function GetStockList(arg1:string):Promise<Array<data.StockBasic>>;
|
export function GetStockList(arg1:string):Promise<Array<data.StockBasic>>;
|
||||||
|
|
||||||
|
@ -1,58 +1,5 @@
|
|||||||
export namespace data {
|
export namespace data {
|
||||||
|
|
||||||
export class FollowedStock {
|
|
||||||
StockCode: string;
|
|
||||||
Name: string;
|
|
||||||
Volume: number;
|
|
||||||
CostPrice: number;
|
|
||||||
Price: number;
|
|
||||||
PriceChange: number;
|
|
||||||
ChangePercent: number;
|
|
||||||
AlarmChangePercent: number;
|
|
||||||
AlarmPrice: number;
|
|
||||||
// Go type: time
|
|
||||||
Time: any;
|
|
||||||
Sort: number;
|
|
||||||
IsDel: number;
|
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
|
||||||
return new FollowedStock(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
|
||||||
if ('string' === typeof source) source = JSON.parse(source);
|
|
||||||
this.StockCode = source["StockCode"];
|
|
||||||
this.Name = source["Name"];
|
|
||||||
this.Volume = source["Volume"];
|
|
||||||
this.CostPrice = source["CostPrice"];
|
|
||||||
this.Price = source["Price"];
|
|
||||||
this.PriceChange = source["PriceChange"];
|
|
||||||
this.ChangePercent = source["ChangePercent"];
|
|
||||||
this.AlarmChangePercent = source["AlarmChangePercent"];
|
|
||||||
this.AlarmPrice = source["AlarmPrice"];
|
|
||||||
this.Time = this.convertValues(source["Time"], null);
|
|
||||||
this.Sort = source["Sort"];
|
|
||||||
this.IsDel = source["IsDel"];
|
|
||||||
}
|
|
||||||
|
|
||||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
|
||||||
if (!a) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
if (a.slice && a.map) {
|
|
||||||
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
|
||||||
} else if ("object" === typeof a) {
|
|
||||||
if (asMap) {
|
|
||||||
for (const key of Object.keys(a)) {
|
|
||||||
a[key] = new classs(a[key]);
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return new classs(a);
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class Settings {
|
export class Settings {
|
||||||
ID: number;
|
ID: number;
|
||||||
// Go type: time
|
// Go type: time
|
||||||
@ -245,6 +192,8 @@ export namespace data {
|
|||||||
"卖四申报": string;
|
"卖四申报": string;
|
||||||
"卖五报价": string;
|
"卖五报价": string;
|
||||||
"卖五申报": string;
|
"卖五申报": string;
|
||||||
|
"市场": string;
|
||||||
|
"盘前盘后": string;
|
||||||
changePercent: number;
|
changePercent: number;
|
||||||
changePrice: number;
|
changePrice: number;
|
||||||
highRate: number;
|
highRate: number;
|
||||||
@ -302,6 +251,8 @@ export namespace data {
|
|||||||
this["卖四申报"] = source["卖四申报"];
|
this["卖四申报"] = source["卖四申报"];
|
||||||
this["卖五报价"] = source["卖五报价"];
|
this["卖五报价"] = source["卖五报价"];
|
||||||
this["卖五申报"] = source["卖五申报"];
|
this["卖五申报"] = source["卖五申报"];
|
||||||
|
this["市场"] = source["市场"];
|
||||||
|
this["盘前盘后"] = source["盘前盘后"];
|
||||||
this.changePercent = source["changePercent"];
|
this.changePercent = source["changePercent"];
|
||||||
this.changePrice = source["changePrice"];
|
this.changePrice = source["changePrice"];
|
||||||
this.highRate = source["highRate"];
|
this.highRate = source["highRate"];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user