From 7b93d4d8ca36cc0181dd70b5ea31f4fc933660fa Mon Sep 17 00:00:00 2001 From: spark Date: Sat, 8 Feb 2025 11:13:17 +0800 Subject: [PATCH] =?UTF-8?q?feat(data):=20=E6=B7=BB=E5=8A=A0=20AIResponseRe?= =?UTF-8?q?sult=E6=A8=A1=E5=9E=8B=E5=B9=B6=E5=AE=9E=E7=8E=B0=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 感谢 @gnim2600 的建议! - 新增 AIResponseResult 模型用于保存 AI 分析结果 - 实现 SaveAIResponseResult 和 GetAIResponseResult 函数 - 在前端添加 AI 分析功能,包括保存和获取分析结果 -优化 AI 分析界面,增加分析时间显示和再次分析按钮 --- app.go | 7 ++++ backend/data/openai_api.go | 19 +++++++++ backend/models/models.go | 18 +++++++- frontend/src/components/stock.vue | 69 +++++++++++++++++++++++++------ frontend/wailsjs/go/main/App.d.ts | 5 +++ frontend/wailsjs/go/main/App.js | 8 ++++ frontend/wailsjs/go/models.ts | 52 +++++++++++++++++++++++ main.go | 2 + 8 files changed, 167 insertions(+), 13 deletions(-) diff --git a/app.go b/app.go index cf27bf2..596f4b6 100644 --- a/app.go +++ b/app.go @@ -424,6 +424,13 @@ func (a *App) NewChatStream(stock, stockCode string) { runtime.EventsEmit(a.ctx, "newChatStream", "DONE") } +func (a *App) SaveAIResponseResult(stockCode, stockName, result string) { + data.NewDeepSeekOpenAi().SaveAIResponseResult(stockCode, stockName, result) +} +func (a *App) GetAIResponseResult(stock string) *models.AIResponseResult { + return data.NewDeepSeekOpenAi().GetAIResponseResult(stock) +} + func GenNotificationMsg(stockInfo *data.StockInfo) string { Price, err := convertor.ToFloat(stockInfo.Price) if err != nil { diff --git a/backend/data/openai_api.go b/backend/data/openai_api.go index 30560d8..d1dac81 100644 --- a/backend/data/openai_api.go +++ b/backend/data/openai_api.go @@ -9,7 +9,9 @@ import ( "github.com/chromedp/chromedp" "github.com/duke-git/lancet/v2/strutil" "github.com/go-resty/resty/v2" + "go-stock/backend/db" "go-stock/backend/logger" + "go-stock/backend/models" "strings" "sync" "time" @@ -208,6 +210,9 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string { client.SetHeader("Authorization", "Bearer "+o.ApiKey) client.SetHeader("Content-Type", "application/json") client.SetRetryCount(3) + if o.TimeOut <= 0 { + o.TimeOut = 300 + } client.SetTimeout(time.Duration(o.TimeOut) * time.Second) resp, err := client.R(). SetDoNotParseResponse(true). @@ -446,3 +451,17 @@ func GetTelegraphList() *[]string { }) return &telegraph } + +func (o OpenAi) SaveAIResponseResult(stockCode, stockName, result string) { + db.Dao.Create(&models.AIResponseResult{ + StockCode: stockCode, + StockName: stockName, + Content: result, + }) +} + +func (o OpenAi) GetAIResponseResult(stock string) *models.AIResponseResult { + var result models.AIResponseResult + db.Dao.Where("stock_code = ?", stock).Order("id desc").First(&result) + return &result +} diff --git a/backend/models/models.go b/backend/models/models.go index 1308f60..3697526 100644 --- a/backend/models/models.go +++ b/backend/models/models.go @@ -1,6 +1,10 @@ package models -import "time" +import ( + "gorm.io/gorm" + "gorm.io/plugin/soft_delete" + "time" +) // @Author spark // @Date 2025/2/6 15:25 @@ -128,3 +132,15 @@ type Commit struct { VerifiedAt interface{} `json:"verified_at"` } `json:"verification"` } + +type AIResponseResult struct { + gorm.Model + StockCode string `json:"stockCode"` + StockName string `json:"stockName"` + Content string `json:"content"` + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"` +} + +func (receiver AIResponseResult) TableName() string { + return "ai_response_result" +} diff --git a/frontend/src/components/stock.vue b/frontend/src/components/stock.vue index 61116be..896a02e 100644 --- a/frontend/src/components/stock.vue +++ b/frontend/src/components/stock.vue @@ -4,11 +4,11 @@ import { Follow, GetConfig, GetFollowList, GetStockList, - Greet, NewChat, NewChatStream, + Greet, SaveAIResponseResult, NewChatStream, SendDingDingMessage, SendDingDingMessageByType, SetAlarmChangePercent, SetCostPriceAndVolume, SetStockSort, - UnFollow + UnFollow, GetAIResponseResult } from '../../wailsjs/go/main/App' import { NAvatar, @@ -152,6 +152,7 @@ EventsOn("newChatStream",async (msg) => { //console.log("newChatStream:->",data.airesult) data.loading = false if (msg === "DONE") { + SaveAIResponseResult(data.code, data.name, data.airesult) message.info("AI分析完成!") message.destroyAll() } else { @@ -448,9 +449,9 @@ function SendMessage(result,type){ // SendDingDingMessage(msg,result["股票代码"]) SendDingDingMessageByType(msg,result["股票代码"],type) } - -function aiCheckStock(stock,stockCode){ +function aiReCheckStock(stock,stockCode) { data.airesult="" + data.time="" data.name=stock data.code=stockCode data.loading=true @@ -461,6 +462,38 @@ function aiCheckStock(stock,stockCode){ NewChatStream(stock,stockCode) } +function aiCheckStock(stock,stockCode){ + GetAIResponseResult(stockCode).then(result => { + if(result.content){ + data.name=stock + data.code=stockCode + data.loading=false + modalShow4.value=true + data.airesult=result.content + const date = new Date(result.CreatedAt); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + data.time=formattedDate + }else{ + data.airesult="" + data.time="" + data.name=stock + data.code=stockCode + data.loading=true + modalShow4.value=true + message.loading("ai检测中...",{ + duration: 0, + }) + NewChatStream(stock,stockCode) + } + }) +} + function getTypeName(type){ switch (type) { @@ -518,7 +551,9 @@ function getHeight() { 取消关注   - AI分析 + + AI分析 + diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index f91270b..3231ea6 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -1,9 +1,12 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import {models} from '../models'; import {data} from '../models'; export function Follow(arg1:string):Promise; +export function GetAIResponseResult(arg1:string):Promise; + export function GetConfig():Promise; export function GetFollowList():Promise>; @@ -16,6 +19,8 @@ export function NewChat(arg1:string):Promise; export function NewChatStream(arg1:string,arg2:string):Promise; +export function SaveAIResponseResult(arg1:string,arg2:string,arg3:string):Promise; + export function SendDingDingMessage(arg1:string,arg2:string):Promise; export function SendDingDingMessageByType(arg1:string,arg2:string,arg3:number):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index d200fbd..addc5ee 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -6,6 +6,10 @@ export function Follow(arg1) { return window['go']['main']['App']['Follow'](arg1); } +export function GetAIResponseResult(arg1) { + return window['go']['main']['App']['GetAIResponseResult'](arg1); +} + export function GetConfig() { return window['go']['main']['App']['GetConfig'](); } @@ -30,6 +34,10 @@ export function NewChatStream(arg1, arg2) { return window['go']['main']['App']['NewChatStream'](arg1, arg2); } +export function SaveAIResponseResult(arg1, arg2, arg3) { + return window['go']['main']['App']['SaveAIResponseResult'](arg1, arg2, arg3); +} + export function SendDingDingMessage(arg1, arg2) { return window['go']['main']['App']['SendDingDingMessage'](arg1, arg2); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 0881055..c32a511 100644 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -329,3 +329,55 @@ export namespace data { } +export namespace models { + + export class AIResponseResult { + ID: number; + // Go type: time + CreatedAt: any; + // Go type: time + UpdatedAt: any; + // Go type: gorm + DeletedAt: any; + stockCode: string; + stockName: string; + content: string; + IsDel: number; + + static createFrom(source: any = {}) { + return new AIResponseResult(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.ID = source["ID"]; + this.CreatedAt = this.convertValues(source["CreatedAt"], null); + this.UpdatedAt = this.convertValues(source["UpdatedAt"], null); + this.DeletedAt = this.convertValues(source["DeletedAt"], null); + this.stockCode = source["stockCode"]; + this.stockName = source["stockName"]; + this.content = source["content"]; + 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; + } + } + +} + diff --git a/main.go b/main.go index 4a3e1af..cccbd77 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( "github.com/wailsapp/wails/v2/pkg/runtime" "go-stock/backend/data" "go-stock/backend/db" + "go-stock/backend/models" "log" "os" goruntime "runtime" @@ -44,6 +45,7 @@ func main() { db.Dao.AutoMigrate(&data.FollowedStock{}) db.Dao.AutoMigrate(&data.IndexBasic{}) db.Dao.AutoMigrate(&data.Settings{}) + db.Dao.AutoMigrate(&models.AIResponseResult{}) if stocksBin != nil && len(stocksBin) > 0 { go initStockData()