Skip to content

Commit 7b93d4d

Browse files
author
spark
committed
feat(data): 添加 AIResponseResult模型并实现相关功能
感谢 @gnim2600 的建议! - 新增 AIResponseResult 模型用于保存 AI 分析结果 - 实现 SaveAIResponseResult 和 GetAIResponseResult 函数 - 在前端添加 AI 分析功能,包括保存和获取分析结果 -优化 AI 分析界面,增加分析时间显示和再次分析按钮
1 parent 3e13ef0 commit 7b93d4d

File tree

8 files changed

+167
-13
lines changed

8 files changed

+167
-13
lines changed

app.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,13 @@ func (a *App) NewChatStream(stock, stockCode string) {
424424
runtime.EventsEmit(a.ctx, "newChatStream", "DONE")
425425
}
426426

427+
func (a *App) SaveAIResponseResult(stockCode, stockName, result string) {
428+
data.NewDeepSeekOpenAi().SaveAIResponseResult(stockCode, stockName, result)
429+
}
430+
func (a *App) GetAIResponseResult(stock string) *models.AIResponseResult {
431+
return data.NewDeepSeekOpenAi().GetAIResponseResult(stock)
432+
}
433+
427434
func GenNotificationMsg(stockInfo *data.StockInfo) string {
428435
Price, err := convertor.ToFloat(stockInfo.Price)
429436
if err != nil {

backend/data/openai_api.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import (
99
"github.com/chromedp/chromedp"
1010
"github.com/duke-git/lancet/v2/strutil"
1111
"github.com/go-resty/resty/v2"
12+
"go-stock/backend/db"
1213
"go-stock/backend/logger"
14+
"go-stock/backend/models"
1315
"strings"
1416
"sync"
1517
"time"
@@ -208,6 +210,9 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
208210
client.SetHeader("Authorization", "Bearer "+o.ApiKey)
209211
client.SetHeader("Content-Type", "application/json")
210212
client.SetRetryCount(3)
213+
if o.TimeOut <= 0 {
214+
o.TimeOut = 300
215+
}
211216
client.SetTimeout(time.Duration(o.TimeOut) * time.Second)
212217
resp, err := client.R().
213218
SetDoNotParseResponse(true).
@@ -446,3 +451,17 @@ func GetTelegraphList() *[]string {
446451
})
447452
return &telegraph
448453
}
454+
455+
func (o OpenAi) SaveAIResponseResult(stockCode, stockName, result string) {
456+
db.Dao.Create(&models.AIResponseResult{
457+
StockCode: stockCode,
458+
StockName: stockName,
459+
Content: result,
460+
})
461+
}
462+
463+
func (o OpenAi) GetAIResponseResult(stock string) *models.AIResponseResult {
464+
var result models.AIResponseResult
465+
db.Dao.Where("stock_code = ?", stock).Order("id desc").First(&result)
466+
return &result
467+
}

backend/models/models.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package models
22

3-
import "time"
3+
import (
4+
"gorm.io/gorm"
5+
"gorm.io/plugin/soft_delete"
6+
"time"
7+
)
48

59
// @Author spark
610
// @Date 2025/2/6 15:25
@@ -128,3 +132,15 @@ type Commit struct {
128132
VerifiedAt interface{} `json:"verified_at"`
129133
} `json:"verification"`
130134
}
135+
136+
type AIResponseResult struct {
137+
gorm.Model
138+
StockCode string `json:"stockCode"`
139+
StockName string `json:"stockName"`
140+
Content string `json:"content"`
141+
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
142+
}
143+
144+
func (receiver AIResponseResult) TableName() string {
145+
return "ai_response_result"
146+
}

frontend/src/components/stock.vue

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import {
44
Follow, GetConfig,
55
GetFollowList,
66
GetStockList,
7-
Greet, NewChat, NewChatStream,
7+
Greet, SaveAIResponseResult, NewChatStream,
88
SendDingDingMessage, SendDingDingMessageByType,
99
SetAlarmChangePercent,
1010
SetCostPriceAndVolume, SetStockSort,
11-
UnFollow
11+
UnFollow, GetAIResponseResult
1212
} from '../../wailsjs/go/main/App'
1313
import {
1414
NAvatar,
@@ -152,6 +152,7 @@ EventsOn("newChatStream",async (msg) => {
152152
//console.log("newChatStream:->",data.airesult)
153153
data.loading = false
154154
if (msg === "DONE") {
155+
SaveAIResponseResult(data.code, data.name, data.airesult)
155156
message.info("AI分析完成!")
156157
message.destroyAll()
157158
} else {
@@ -448,9 +449,9 @@ function SendMessage(result,type){
448449
// SendDingDingMessage(msg,result["股票代码"])
449450
SendDingDingMessageByType(msg,result["股票代码"],type)
450451
}
451-
452-
function aiCheckStock(stock,stockCode){
452+
function aiReCheckStock(stock,stockCode) {
453453
data.airesult=""
454+
data.time=""
454455
data.name=stock
455456
data.code=stockCode
456457
data.loading=true
@@ -461,6 +462,38 @@ function aiCheckStock(stock,stockCode){
461462
NewChatStream(stock,stockCode)
462463
}
463464
465+
function aiCheckStock(stock,stockCode){
466+
GetAIResponseResult(stockCode).then(result => {
467+
if(result.content){
468+
data.name=stock
469+
data.code=stockCode
470+
data.loading=false
471+
modalShow4.value=true
472+
data.airesult=result.content
473+
const date = new Date(result.CreatedAt);
474+
const year = date.getFullYear();
475+
const month = String(date.getMonth() + 1).padStart(2, '0');
476+
const day = String(date.getDate()).padStart(2, '0');
477+
const hours = String(date.getHours()).padStart(2, '0');
478+
const minutes = String(date.getMinutes()).padStart(2, '0');
479+
const seconds = String(date.getSeconds()).padStart(2, '0');
480+
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
481+
data.time=formattedDate
482+
}else{
483+
data.airesult=""
484+
data.time=""
485+
data.name=stock
486+
data.code=stockCode
487+
data.loading=true
488+
modalShow4.value=true
489+
message.loading("ai检测中...",{
490+
duration: 0,
491+
})
492+
NewChatStream(stock,stockCode)
493+
}
494+
})
495+
}
496+
464497
function getTypeName(type){
465498
switch (type)
466499
{
@@ -518,7 +551,9 @@ function getHeight() {
518551
<n-button size="tiny" secondary type="primary" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
519552
取消关注
520553
</n-button>&nbsp;
521-
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning" @click="aiCheckStock(result['股票名称'],result['股票代码'])"> AI分析 </n-button>
554+
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning" @click="aiCheckStock(result['股票名称'],result['股票代码'])">
555+
AI分析
556+
</n-button>
522557
523558
</template>
524559
<template #footer>
@@ -609,18 +644,28 @@ function getHeight() {
609644
<n-image :src="data.kURL" />
610645
</n-modal>
611646
612-
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;height: 480px" :title="'['+data.name+']AI分析结果'" >
647+
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;height: 500px" :title="'['+data.name+']AI分析结果'" >
613648
<n-spin size="small" :show="data.loading">
614649
<MdPreview ref="mdPreviewRef" style="height: 380px;text-align: left" :modelValue="data.airesult" :theme="'dark'"/>
615650
</n-spin>
651+
<template #header-extra>
652+
653+
</template>
654+
<template #footer>
655+
<n-flex justify="space-between">
656+
<n-text type="error" v-if="data.time" >分析时间:{{data.time}}</n-text>
657+
<n-button size="tiny" type="warning" @click="aiReCheckStock(data.name,data.code)">再次分析</n-button>
658+
</n-flex>
659+
</template>
616660
</n-modal>
617661
</template>
618662
619663
<style scoped>
620-
h3 {
621-
text-align: center;
622-
}
623-
#总结 {
624-
text-align: center;
625-
}
664+
.md-editor-preview h3{
665+
text-align: center !important;
666+
}
667+
668+
.md-editor-preview p{
669+
text-align: left !important;
670+
}
626671
</style>

frontend/wailsjs/go/main/App.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
22
// This file is automatically generated. DO NOT EDIT
3+
import {models} from '../models';
34
import {data} from '../models';
45

56
export function Follow(arg1:string):Promise<string>;
67

8+
export function GetAIResponseResult(arg1:string):Promise<models.AIResponseResult>;
9+
710
export function GetConfig():Promise<data.Settings>;
811

912
export function GetFollowList():Promise<Array<data.FollowedStock>>;
@@ -16,6 +19,8 @@ export function NewChat(arg1:string):Promise<string>;
1619

1720
export function NewChatStream(arg1:string,arg2:string):Promise<void>;
1821

22+
export function SaveAIResponseResult(arg1:string,arg2:string,arg3:string):Promise<void>;
23+
1924
export function SendDingDingMessage(arg1:string,arg2:string):Promise<string>;
2025

2126
export function SendDingDingMessageByType(arg1:string,arg2:string,arg3:number):Promise<string>;

frontend/wailsjs/go/main/App.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ export function Follow(arg1) {
66
return window['go']['main']['App']['Follow'](arg1);
77
}
88

9+
export function GetAIResponseResult(arg1) {
10+
return window['go']['main']['App']['GetAIResponseResult'](arg1);
11+
}
12+
913
export function GetConfig() {
1014
return window['go']['main']['App']['GetConfig']();
1115
}
@@ -30,6 +34,10 @@ export function NewChatStream(arg1, arg2) {
3034
return window['go']['main']['App']['NewChatStream'](arg1, arg2);
3135
}
3236

37+
export function SaveAIResponseResult(arg1, arg2, arg3) {
38+
return window['go']['main']['App']['SaveAIResponseResult'](arg1, arg2, arg3);
39+
}
40+
3341
export function SendDingDingMessage(arg1, arg2) {
3442
return window['go']['main']['App']['SendDingDingMessage'](arg1, arg2);
3543
}

frontend/wailsjs/go/models.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,55 @@ export namespace data {
329329

330330
}
331331

332+
export namespace models {
333+
334+
export class AIResponseResult {
335+
ID: number;
336+
// Go type: time
337+
CreatedAt: any;
338+
// Go type: time
339+
UpdatedAt: any;
340+
// Go type: gorm
341+
DeletedAt: any;
342+
stockCode: string;
343+
stockName: string;
344+
content: string;
345+
IsDel: number;
346+
347+
static createFrom(source: any = {}) {
348+
return new AIResponseResult(source);
349+
}
350+
351+
constructor(source: any = {}) {
352+
if ('string' === typeof source) source = JSON.parse(source);
353+
this.ID = source["ID"];
354+
this.CreatedAt = this.convertValues(source["CreatedAt"], null);
355+
this.UpdatedAt = this.convertValues(source["UpdatedAt"], null);
356+
this.DeletedAt = this.convertValues(source["DeletedAt"], null);
357+
this.stockCode = source["stockCode"];
358+
this.stockName = source["stockName"];
359+
this.content = source["content"];
360+
this.IsDel = source["IsDel"];
361+
}
362+
363+
convertValues(a: any, classs: any, asMap: boolean = false): any {
364+
if (!a) {
365+
return a;
366+
}
367+
if (a.slice && a.map) {
368+
return (a as any[]).map(elem => this.convertValues(elem, classs));
369+
} else if ("object" === typeof a) {
370+
if (asMap) {
371+
for (const key of Object.keys(a)) {
372+
a[key] = new classs(a[key]);
373+
}
374+
return a;
375+
}
376+
return new classs(a);
377+
}
378+
return a;
379+
}
380+
}
381+
382+
}
383+

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/wailsapp/wails/v2/pkg/runtime"
1515
"go-stock/backend/data"
1616
"go-stock/backend/db"
17+
"go-stock/backend/models"
1718
"log"
1819
"os"
1920
goruntime "runtime"
@@ -44,6 +45,7 @@ func main() {
4445
db.Dao.AutoMigrate(&data.FollowedStock{})
4546
db.Dao.AutoMigrate(&data.IndexBasic{})
4647
db.Dao.AutoMigrate(&data.Settings{})
48+
db.Dao.AutoMigrate(&models.AIResponseResult{})
4749

4850
if stocksBin != nil && len(stocksBin) > 0 {
4951
go initStockData()

0 commit comments

Comments
 (0)