feat(frontend):设置页面添加弹幕功能开关

(今天看见某位朋友在弹幕中说,关掉弹幕。那就如你所愿,你可以自己决定是否显示弹幕了😎)
- 在设置页面添加弹幕功能开关
- 调整数据刷新间隔和启动时更新信息的布局
- 在股票页面实现弹幕功能,根据设置开关控制是否显示弹幕
- 调整应用窗口高度比例
- 优化 OpenAI API 请求时的 URL 处理
This commit is contained in:
ArvinLovegood 2025-02-26 22:17:17 +08:00
parent 8a7e0140eb
commit 2aba86e424
6 changed files with 26 additions and 9 deletions

View File

@ -301,7 +301,7 @@ func (o OpenAi) NewChatStream(stock, stockCode, userQuestion string) <-chan map[
"content": question, "content": question,
}) })
client := resty.New() client := resty.New()
client.SetBaseURL(o.BaseUrl) client.SetBaseURL(strutil.Trim(o.BaseUrl))
client.SetHeader("Authorization", "Bearer "+o.ApiKey) client.SetHeader("Authorization", "Bearer "+o.ApiKey)
client.SetHeader("Content-Type", "application/json") client.SetHeader("Content-Type", "application/json")
//client.SetRetryCount(3) //client.SetRetryCount(3)

View File

@ -28,6 +28,7 @@ type Settings struct {
QuestionTemplate string `json:"questionTemplate"` QuestionTemplate string `json:"questionTemplate"`
CrawlTimeOut int64 `json:"crawlTimeOut"` CrawlTimeOut int64 `json:"crawlTimeOut"`
KDays int64 `json:"kDays"` KDays int64 `json:"kDays"`
EnableDanmu bool `json:"enableDanmu"`
} }
func (receiver Settings) TableName() string { func (receiver Settings) TableName() string {
@ -67,6 +68,7 @@ func (s SettingsApi) UpdateConfig() string {
"question_template": s.Config.QuestionTemplate, "question_template": s.Config.QuestionTemplate,
"crawl_time_out": s.Config.CrawlTimeOut, "crawl_time_out": s.Config.CrawlTimeOut,
"k_days": s.Config.KDays, "k_days": s.Config.KDays,
"enable_danmu": s.Config.EnableDanmu,
}) })
} else { } else {
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config) logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
@ -89,6 +91,7 @@ func (s SettingsApi) UpdateConfig() string {
QuestionTemplate: s.Config.QuestionTemplate, QuestionTemplate: s.Config.QuestionTemplate,
CrawlTimeOut: s.Config.CrawlTimeOut, CrawlTimeOut: s.Config.CrawlTimeOut,
KDays: s.Config.KDays, KDays: s.Config.KDays,
EnableDanmu: s.Config.EnableDanmu,
}) })
} }
return "保存成功!" return "保存成功!"

View File

@ -32,7 +32,8 @@ const formValue = ref({
questionTemplate: "{{stockName}}分析和总结", questionTemplate: "{{stockName}}分析和总结",
crawlTimeOut:30, crawlTimeOut:30,
kDays:30, kDays:30,
} },
enableDanmu:false,
}) })
onMounted(()=>{ onMounted(()=>{
@ -61,6 +62,7 @@ onMounted(()=>{
crawlTimeOut:res.crawlTimeOut, crawlTimeOut:res.crawlTimeOut,
kDays:res.kDays, kDays:res.kDays,
} }
formValue.value.enableDanmu = res.enableDanmu
console.log(res) console.log(res)
}) })
//message.info("") //message.info("")
@ -86,7 +88,8 @@ function saveConfig(){
openAiApiTimeOut:formValue.value.openAI.timeout, openAiApiTimeOut:formValue.value.openAI.timeout,
questionTemplate:formValue.value.openAI.questionTemplate, questionTemplate:formValue.value.openAI.questionTemplate,
crawlTimeOut:formValue.value.openAI.crawlTimeOut, crawlTimeOut:formValue.value.openAI.crawlTimeOut,
kDays:formValue.value.openAI.kDays kDays:formValue.value.openAI.kDays,
enableDanmu:formValue.value.enableDanmu
}) })
//console.log("Settings",config) //console.log("Settings",config)
@ -157,6 +160,7 @@ function importConfig(){
crawlTimeOut:config.crawlTimeOut, crawlTimeOut:config.crawlTimeOut,
kDays:config.kDays kDays:config.kDays
} }
formValue.value.enableDanmu = config.enableDanmu
// formRef.value.resetFields() // formRef.value.resetFields()
}; };
reader.readAsText(file); reader.readAsText(file);
@ -191,10 +195,10 @@ window.onerror = function (event, source, lineno, colno, error) {
<n-form-item-gi :span="10" label="Tushare api token" path="tushareToken" > <n-form-item-gi :span="10" label="Tushare api token" path="tushareToken" >
<n-input type="text" placeholder="Tushare api token" v-model:value="formValue.tushareToken" clearable /> <n-input type="text" placeholder="Tushare api token" v-model:value="formValue.tushareToken" clearable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="6" label="启动时更新A股/指数信息:" path="updateBasicInfoOnStart" > <n-form-item-gi :span="4" label="启动时更新A股/指数信息:" path="updateBasicInfoOnStart" >
<n-switch v-model:value="formValue.updateBasicInfoOnStart" /> <n-switch v-model:value="formValue.updateBasicInfoOnStart" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="6" label="数据刷新间隔(重启生效)" path="refreshInterval" > <n-form-item-gi :span="5" label="数据刷新间隔(重启生效)" path="refreshInterval" >
<n-input-number v-model:value="formValue.refreshInterval" placeholder="请输入数据刷新间隔(秒)"> <n-input-number v-model:value="formValue.refreshInterval" placeholder="请输入数据刷新间隔(秒)">
<template #suffix> <template #suffix>
@ -213,6 +217,9 @@ window.onerror = function (event, source, lineno, colno, error) {
<n-form-item-gi :span="6" label="是否启用本地推送:" path="localPush.enable" > <n-form-item-gi :span="6" label="是否启用本地推送:" path="localPush.enable" >
<n-switch v-model:value="formValue.localPush.enable" /> <n-switch v-model:value="formValue.localPush.enable" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="5" label="弹幕功能:" path="enableDanmu" >
<n-switch v-model:value="formValue.enableDanmu" />
</n-form-item-gi>
<n-form-item-gi :span="22" v-if="formValue.dingPush.enable" label="钉钉机器人接口地址:" path="dingPush.dingRobot" > <n-form-item-gi :span="22" v-if="formValue.dingPush.enable" label="钉钉机器人接口地址:" path="dingPush.dingRobot" >
<n-input placeholder="请输入钉钉机器人接口地址" v-model:value="formValue.dingPush.dingRobot"/> <n-input placeholder="请输入钉钉机器人接口地址" v-model:value="formValue.dingPush.dingRobot"/>
<n-button type="primary" @click="sendTestNotice">发送测试通知</n-button> <n-button type="primary" @click="sendTestNotice">发送测试通知</n-button>

View File

@ -50,7 +50,7 @@ import html2canvas from "html2canvas";
import {asBlob} from 'html-docx-js-typescript'; import {asBlob} from 'html-docx-js-typescript';
import vueDanmaku from 'vue3-danmaku' import vueDanmaku from 'vue3-danmaku'
const danmus = ref(['欢迎回来~']) const danmus = ref([])
const ws = ref(null) const ws = ref(null)
const toolbars = [0]; const toolbars = [0];
@ -100,6 +100,7 @@ const data = reactive({
airesult: "", airesult: "",
openAiEnable: false, openAiEnable: false,
loading: true, loading: true,
enableDanmu: false,
}) })
const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/master/build/appicon.png'); const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/master/build/appicon.png');
@ -137,6 +138,9 @@ onBeforeMount(()=>{
if (result.openAiEnable) { if (result.openAiEnable) {
data.openAiEnable = true data.openAiEnable = true
} }
if (result.enableDanmu) {
data.enableDanmu = true
}
}) })
}) })
@ -163,8 +167,9 @@ onMounted(() => {
}; };
ws.value.onmessage = (event) => { ws.value.onmessage = (event) => {
const message = event.data; if(data.enableDanmu){
danmus.value.push(message); danmus.value.push(event.data);
}
}; };
ws.value.onerror = (error) => { ws.value.onerror = (error) => {

View File

@ -79,6 +79,7 @@ export namespace data {
questionTemplate: string; questionTemplate: string;
crawlTimeOut: number; crawlTimeOut: number;
kDays: number; kDays: number;
enableDanmu: boolean;
static createFrom(source: any = {}) { static createFrom(source: any = {}) {
return new Settings(source); return new Settings(source);
@ -108,6 +109,7 @@ export namespace data {
this.questionTemplate = source["questionTemplate"]; this.questionTemplate = source["questionTemplate"];
this.crawlTimeOut = source["crawlTimeOut"]; this.crawlTimeOut = source["crawlTimeOut"];
this.kDays = source["kDays"]; this.kDays = source["kDays"];
this.enableDanmu = source["enableDanmu"];
} }
convertValues(a: any, classs: any, asMap: boolean = false): any { convertValues(a: any, classs: any, asMap: boolean = false): any {

View File

@ -121,7 +121,7 @@ func main() {
err = wails.Run(&options.App{ err = wails.Run(&options.App{
Title: "go-stock", Title: "go-stock",
Width: width * 4 / 5, Width: width * 4 / 5,
Height: height * 2 / 3, Height: height * 4 / 5,
MinWidth: 1024, MinWidth: 1024,
MinHeight: 768, MinHeight: 768,
MaxWidth: width, MaxWidth: width,