Compare commits
13 Commits
v2025.7.6.
...
v2025.7.8.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d224ccfc4 | ||
|
|
a66f2156f1 | ||
|
|
e90727773f | ||
|
|
89dcb713be | ||
|
|
6f4b21207d | ||
|
|
f51e3d863a | ||
|
|
c180c2a5f8 | ||
|
|
3ba18e8ef2 | ||
|
|
f0314187e5 | ||
|
|
6440885688 | ||
|
|
2dd4f072b2 | ||
|
|
b5843bcdb8 | ||
|
|
c65d0b79f4 |
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
tags:
|
||||
# Match any new tag
|
||||
- '*-release'
|
||||
- '*-dev'
|
||||
|
||||
env:
|
||||
# Necessary for most environments as build failure can occur due to OOM issues
|
||||
@@ -21,10 +22,6 @@ jobs:
|
||||
- name: 'go-stock-windows-amd64.exe'
|
||||
platform: 'windows/amd64'
|
||||
os: 'windows-latest'
|
||||
- name: 'go-stock-windows-arm64.exe'
|
||||
platform: 'windows/arm64'
|
||||
os: 'windows-latest'
|
||||
arch: arm64
|
||||
# - name: 'go-stock-linux-amd64'
|
||||
# platform: 'linux/amd64'
|
||||
# os: 'ubuntu-latest'
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
| 不再强制依赖Chrome浏览器 | ✅ | 默认使用edge浏览器抓取新闻资讯 |
|
||||
|
||||
## 👀 更新日志
|
||||
### 2025.07.08 实现软件自动更新功能
|
||||
### 2025.07.07 卡片添加迷你分时图
|
||||
### 2025.07.05 MacOs支持
|
||||
### 2025.07.01 AI分析集成工具函数,AI分析将更加智能
|
||||
### 2025.06.30 添加指标选股功能
|
||||
### 2025.06.27 添加财经日历和重大事件时间轴功能
|
||||
|
||||
51
app.go
51
app.go
@@ -1,9 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/inconshreveable/go-update"
|
||||
"go-stock/backend/data"
|
||||
"go-stock/backend/db"
|
||||
"go-stock/backend/logger"
|
||||
@@ -111,6 +113,13 @@ func (a *App) CheckUpdate() {
|
||||
}
|
||||
logger.SugaredLogger.Infof("releaseVersion:%+v", releaseVersion.TagName)
|
||||
if releaseVersion.TagName != Version {
|
||||
go runtime.EventsEmit(a.ctx, "newsPush", map[string]any{
|
||||
"time": "发现新版本:" + releaseVersion.TagName,
|
||||
"isRed": false,
|
||||
"source": "go-stock",
|
||||
"content": fmt.Sprintf("当前版本:%s, 最新版本:%s,开始下载...", Version, releaseVersion.TagName),
|
||||
})
|
||||
|
||||
tag := &models.Tag{}
|
||||
_, err = resty.New().R().
|
||||
SetResult(tag).
|
||||
@@ -118,6 +127,7 @@ func (a *App) CheckUpdate() {
|
||||
if err == nil {
|
||||
releaseVersion.Tag = *tag
|
||||
}
|
||||
|
||||
commit := &models.Commit{}
|
||||
_, err = resty.New().R().
|
||||
SetResult(commit).
|
||||
@@ -126,7 +136,46 @@ func (a *App) CheckUpdate() {
|
||||
releaseVersion.Commit = *commit
|
||||
}
|
||||
|
||||
go runtime.EventsEmit(a.ctx, "updateVersion", releaseVersion)
|
||||
if !IsWindows() {
|
||||
go runtime.EventsEmit(a.ctx, "updateVersion", releaseVersion)
|
||||
return
|
||||
}
|
||||
|
||||
downloadUrl := fmt.Sprintf("https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-windows-amd64.exe", releaseVersion.TagName)
|
||||
resp, err := resty.New().R().Get(downloadUrl)
|
||||
if err != nil {
|
||||
go runtime.EventsEmit(a.ctx, "newsPush", map[string]any{
|
||||
"time": "新版本:" + releaseVersion.TagName,
|
||||
"isRed": true,
|
||||
"source": "go-stock",
|
||||
"content": "新版本下载失败,请前往 https://github.com/ArvinLovegood/go-stock/releases 手动下载替换文件。",
|
||||
})
|
||||
return
|
||||
}
|
||||
body := resp.Body()
|
||||
// 验证下载文件的哈希值
|
||||
//hash := sha256.Sum256(body)
|
||||
//actualSHA256 := hex.EncodeToString(hash[:])
|
||||
//logger.SugaredLogger.Infof("actualSHA256: %s", actualSHA256)
|
||||
//if actualSHA256 != releaseVersion.Commit.Sha {
|
||||
// logger.SugaredLogger.Errorf("下载文件sha256校验失败")
|
||||
// logger.SugaredLogger.Errorf("actualSHA256: %s Commit-Sha:%s", actualSHA256, releaseVersion.Commit.Sha)
|
||||
// return
|
||||
//}
|
||||
// 使用go-update库进行更新
|
||||
err = update.Apply(bytes.NewReader(body), update.Options{})
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Error("更新失败: ", err.Error())
|
||||
go runtime.EventsEmit(a.ctx, "updateVersion", releaseVersion)
|
||||
return
|
||||
} else {
|
||||
go runtime.EventsEmit(a.ctx, "newsPush", map[string]any{
|
||||
"time": "新版本:" + releaseVersion.TagName,
|
||||
"isRed": true,
|
||||
"source": "go-stock",
|
||||
"content": "版本更新完成,下次重启软件生效.",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,11 @@ type OpenAi struct {
|
||||
BrowserPath string `json:"browser_path"`
|
||||
}
|
||||
|
||||
func (o OpenAi) String() string {
|
||||
return fmt.Sprintf("OpenAi{BaseUrl: %s, Model: %s, MaxTokens: %d, Temperature: %.2f, Prompt: %s, TimeOut: %d, QuestionTemplate: %s, CrawlTimeOut: %d, KDays: %d, BrowserPath: %s, ApiKey: [MASKED]}",
|
||||
o.BaseUrl, o.Model, o.MaxTokens, o.Temperature, o.Prompt, o.TimeOut, o.QuestionTemplate, o.CrawlTimeOut, o.KDays, o.BrowserPath)
|
||||
}
|
||||
|
||||
func NewDeepSeekOpenAi(ctx context.Context) *OpenAi {
|
||||
config := GetConfig()
|
||||
if config.OpenAiEnable {
|
||||
@@ -140,8 +145,8 @@ func (o OpenAi) NewSummaryStockNewsStreamWithTools(userQuestion string, sysPromp
|
||||
go func() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic :%s", err)
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic config:%v", o)
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic: %s", err)
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic config: %s", o.String())
|
||||
}
|
||||
}()
|
||||
defer close(ch)
|
||||
@@ -264,7 +269,7 @@ func (o OpenAi) NewSummaryStockNewsStream(userQuestion string, sysPromptId *int)
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic :%s", err)
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic config:%v", o)
|
||||
logger.SugaredLogger.Errorf("NewSummaryStockNewsStream goroutine panic config:%s", o.String())
|
||||
}
|
||||
}()
|
||||
defer close(ch)
|
||||
@@ -356,7 +361,7 @@ func (o OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptId
|
||||
if err := recover(); err != nil {
|
||||
logger.SugaredLogger.Errorf("NewChatStream goroutine panic :%s", err)
|
||||
logger.SugaredLogger.Errorf("NewChatStream goroutine panic stock:%s stockCode:%s", stock, stockCode)
|
||||
logger.SugaredLogger.Errorf("NewChatStream goroutine panic config:%v", o)
|
||||
logger.SugaredLogger.Errorf("NewChatStream goroutine panic config:%s", o.String())
|
||||
}
|
||||
}()
|
||||
defer close(ch)
|
||||
|
||||
@@ -44,9 +44,9 @@ const enableNews = ref(false)
|
||||
const contentStyle = ref("")
|
||||
const enableFund = ref(false)
|
||||
const enableDarkTheme = ref(null)
|
||||
const content = ref('数据来源于网络,仅供参考;投资有风险,入市需谨慎\n\n未经授权,禁止商业目的!')
|
||||
const content = ref('未经授权,禁止商业目的!\n\n数据来源于网络,仅供参考;投资有风险,入市需谨慎')
|
||||
const isFullscreen = ref(false)
|
||||
const activeKey = ref('')
|
||||
const activeKey = ref('stock')
|
||||
const containerRef = ref({})
|
||||
const realtimeProfit = ref(0)
|
||||
const telegraph = ref([])
|
||||
@@ -64,7 +64,10 @@ const menuOptions = ref([
|
||||
groupId: 0,
|
||||
},
|
||||
params: {},
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'stock'
|
||||
},
|
||||
},
|
||||
{default: () => '股票自选',}
|
||||
),
|
||||
@@ -79,6 +82,7 @@ const menuOptions = ref([
|
||||
href: '#',
|
||||
type: 'info',
|
||||
onClick: () => {
|
||||
activeKey.value = 'stock'
|
||||
//console.log("push",item)
|
||||
router.push({
|
||||
name: 'stock',
|
||||
@@ -114,6 +118,7 @@ const menuOptions = ref([
|
||||
params: {}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '市场快讯'})
|
||||
},
|
||||
},
|
||||
@@ -135,6 +140,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '市场快讯'})
|
||||
},
|
||||
},
|
||||
@@ -156,6 +162,7 @@ const menuOptions = ref([
|
||||
},
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '全球股指'})
|
||||
},
|
||||
},
|
||||
@@ -177,6 +184,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '指标行情'})
|
||||
},
|
||||
},
|
||||
@@ -198,6 +206,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '行业排名'})
|
||||
},
|
||||
},
|
||||
@@ -219,6 +228,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '个股资金流向'})
|
||||
},
|
||||
},
|
||||
@@ -240,6 +250,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '龙虎榜'})
|
||||
},
|
||||
},
|
||||
@@ -261,6 +272,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '个股研报'})
|
||||
},
|
||||
},
|
||||
@@ -282,6 +294,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '公司公告'})
|
||||
},
|
||||
},
|
||||
@@ -303,6 +316,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '行业研究'})
|
||||
},
|
||||
},
|
||||
@@ -324,6 +338,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '当前热门'})
|
||||
},
|
||||
},
|
||||
@@ -345,6 +360,7 @@ const menuOptions = ref([
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'market'
|
||||
EventsEmit("changeMarketTab", {ID: 0, name: '指标选股'})
|
||||
},
|
||||
},
|
||||
@@ -362,8 +378,13 @@ const menuOptions = ref([
|
||||
{
|
||||
to: {
|
||||
name: 'fund',
|
||||
params: {},
|
||||
}
|
||||
query: {
|
||||
name: '基金自选',
|
||||
},
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'fund'
|
||||
},
|
||||
},
|
||||
{default: () => '基金自选',}
|
||||
),
|
||||
@@ -386,7 +407,12 @@ const menuOptions = ref([
|
||||
{
|
||||
to: {
|
||||
name: 'settings',
|
||||
params: {}
|
||||
query: {
|
||||
name:"设置",
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'settings'
|
||||
},
|
||||
}
|
||||
},
|
||||
{default: () => '设置'}
|
||||
@@ -401,8 +427,13 @@ const menuOptions = ref([
|
||||
{
|
||||
to: {
|
||||
name: 'about',
|
||||
params: {}
|
||||
}
|
||||
query: {
|
||||
name:"关于",
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
activeKey.value = 'about'
|
||||
},
|
||||
},
|
||||
{default: () => '关于'}
|
||||
),
|
||||
@@ -451,6 +482,7 @@ function renderIcon(icon) {
|
||||
}
|
||||
|
||||
function toggleFullscreen(e) {
|
||||
activeKey.value = 'full'
|
||||
//console.log(e)
|
||||
if (isFullscreen.value) {
|
||||
WindowUnfullscreen()
|
||||
|
||||
@@ -80,7 +80,7 @@ EventsOn("updateVersion",async (msg) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-space vertical size="large">
|
||||
<n-space vertical size="large" style="--wails-draggable:drag">
|
||||
<!-- 软件描述 -->
|
||||
<n-card size="large">
|
||||
<n-divider title-placement="center">关于软件</n-divider>
|
||||
|
||||
@@ -199,6 +199,7 @@ function getAiSummary() {
|
||||
summaryModal.value = true
|
||||
loading.value = true
|
||||
GetAIResponseResult("市场资讯").then(result => {
|
||||
loading.value = false
|
||||
if (result.content) {
|
||||
aiSummary.value = result.content
|
||||
question.value = result.question
|
||||
@@ -310,7 +311,7 @@ function ReFlesh(source) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-card>
|
||||
<n-card style="--wails-draggable:drag">
|
||||
<n-tabs type="line" animated @update-value="updateTab" :value="nowTab">
|
||||
<n-tab-pane name="市场快讯" tab="市场快讯">
|
||||
<n-grid :cols="2" :y-gap="0">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
|
||||
import {computed, onBeforeUnmount, onMounted, ref} from "vue";
|
||||
import {h, onBeforeUnmount, onMounted, ref} from "vue";
|
||||
import {
|
||||
AddPrompt, DelPrompt,
|
||||
ExportConfig,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
SendDingDingMessageByType,
|
||||
UpdateConfig
|
||||
} from "../../wailsjs/go/main/App";
|
||||
import {useMessage} from "naive-ui";
|
||||
import {NTag, useMessage} from "naive-ui";
|
||||
import {data, models} from "../../wailsjs/go/models";
|
||||
import {EventsEmit} from "../../wailsjs/runtime";
|
||||
const message = useMessage()
|
||||
@@ -267,12 +267,13 @@ function deletePrompt(ID){
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-flex justify="left" style="margin-top: 12px;padding-left: 12px;">
|
||||
<n-flex justify="left" style="text-align: left;--wails-draggable:drag" >
|
||||
<n-form ref="formRef" :label-placement="'left'" :label-align="'left'" >
|
||||
<n-grid :cols="24" :x-gap="24" style="text-align: left" :layout-shift-disabled="true">
|
||||
<n-gi :span="24">
|
||||
<n-text type="success" style="font-size: 25px;font-weight: bold">基础设置</n-text>
|
||||
</n-gi>
|
||||
<n-card :title="()=> h(NTag, { type: 'primary',bordered:false },()=> '基础设置')" size="small" >
|
||||
<n-grid :cols="24" :x-gap="24" style="text-align: left" >
|
||||
<!-- <n-gi :span="24">-->
|
||||
<!-- <n-text type="success" style="font-size: 25px;font-weight: bold">基础设置</n-text>-->
|
||||
<!-- </n-gi>-->
|
||||
<n-form-item-gi :span="10" label="Tushare Token:" path="tushareToken" >
|
||||
<n-input type="text" placeholder="Tushare api token" v-model:value="formValue.tushareToken" clearable />
|
||||
</n-form-item-gi>
|
||||
@@ -296,11 +297,14 @@ function deletePrompt(ID){
|
||||
<n-switch v-model:value="formValue.enableFund" />
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
</n-card>
|
||||
|
||||
|
||||
<n-card :title="()=> h(NTag, { type: 'primary',bordered:false },()=> '通知设置')" size="small" >
|
||||
<n-grid :cols="24" :x-gap="24" style="text-align: left">
|
||||
<n-gi :span="24">
|
||||
<n-text type="success" style="font-size: 25px;font-weight: bold">通知设置</n-text>
|
||||
</n-gi>
|
||||
<!-- <n-gi :span="24">-->
|
||||
<!-- <n-text type="success" style="font-size: 25px;font-weight: bold">通知设置</n-text>-->
|
||||
<!-- </n-gi>-->
|
||||
<n-form-item-gi :span="4" label="钉钉推送:" path="dingPush.enable" >
|
||||
<n-switch v-model:value="formValue.dingPush.enable" />
|
||||
</n-form-item-gi>
|
||||
@@ -321,11 +325,13 @@ function deletePrompt(ID){
|
||||
<n-button type="primary" @click="sendTestNotice">发送测试通知</n-button>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
</n-card>
|
||||
|
||||
<n-card :title="()=> h(NTag, { type: 'primary',bordered:false },()=> 'AI设置')" size="small" >
|
||||
<n-grid :cols="24" :x-gap="24" style="text-align: left;">
|
||||
<n-gi :span="24">
|
||||
<n-text type="success" style="font-size: 25px;font-weight: bold">OpenAI设置</n-text>
|
||||
</n-gi>
|
||||
<!-- <n-gi :span="24">-->
|
||||
<!-- <n-text type="success" style="font-size: 25px;font-weight: bold">OpenAI设置</n-text>-->
|
||||
<!-- </n-gi>-->
|
||||
<n-form-item-gi :span="3" label="AI诊股:" path="openAI.enable" >
|
||||
<n-switch v-model:value="formValue.openAI.enable" />
|
||||
</n-form-item-gi>
|
||||
@@ -376,28 +382,38 @@ function deletePrompt(ID){
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
<n-gi :span="24">
|
||||
<n-grid :cols="24">
|
||||
<n-gi :span="24">
|
||||
<n-space justify="center">
|
||||
<n-button type="warning" @click="managePrompts">
|
||||
<n-button type="warning" @click="managePrompts">
|
||||
添加提示词模板
|
||||
</n-button>
|
||||
<n-button type="primary" @click="saveConfig">
|
||||
保存
|
||||
</n-button>
|
||||
<n-button type="info" @click="exportConfig">
|
||||
导出
|
||||
</n-button>
|
||||
<n-button type="error" @click="importConfig">
|
||||
导入
|
||||
</n-button>
|
||||
<n-button type="primary" @click="saveConfig">
|
||||
保存
|
||||
</n-button>
|
||||
<n-button type="info" @click="exportConfig">
|
||||
导出
|
||||
</n-button>
|
||||
<n-button type="error" @click="importConfig">
|
||||
导入
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-gi>
|
||||
</n-gi>
|
||||
<n-gi :span="24" v-if="promptTemplates.length>0" type="warning">
|
||||
<n-flex justify="start" style="margin-top: 4px" >
|
||||
<n-text type="warning" >
|
||||
<n-flex justify="left" >
|
||||
<n-tag :bordered="false" type="warning" > 提示词模板:</n-tag>
|
||||
<n-tag size="medium" secondary v-if="promptTemplates.length>0" v-for="prompt in promptTemplates" closable @close="deletePrompt(prompt.ID)" @click="editPrompt(prompt)" :title="prompt.content"
|
||||
:type="prompt.type==='模型系统Prompt'?'success':'info'" :bordered="false"> {{ prompt.name }}
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
</n-text>
|
||||
</n-flex>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-card>
|
||||
</n-form>
|
||||
<n-gi :span="24" v-if="promptTemplates.length>0" v-for="prompt in promptTemplates" >
|
||||
<n-flex justify="start">
|
||||
<n-tag closable @close="deletePrompt(prompt.ID)" @click="editPrompt(prompt)" :title="prompt.content" :type="prompt.type==='模型系统Prompt'?'success':'info'" :bordered="false"> {{prompt.name}} </n-tag>
|
||||
</n-flex>
|
||||
</n-gi>
|
||||
</n-flex>
|
||||
<n-modal v-model:show="showManagePromptsModal" closable :mask-closable="false">
|
||||
<n-card
|
||||
@@ -442,5 +458,9 @@ function deletePrompt(ID){
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.cardHeaderClass{
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@@ -64,6 +64,7 @@ import {keys, padStart} from "lodash";
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import MoneyTrend from "./moneyTrend.vue";
|
||||
import {TaskTools} from "@vicons/carbon";
|
||||
import StockSparkLine from "./stockSparkLine.vue";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -1796,8 +1797,8 @@ function searchStockReport(stockCode) {
|
||||
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true"
|
||||
:title="result['股票名称']" :closable="false"
|
||||
@close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
<n-grid :cols="1" :y-gap="6">
|
||||
<n-gi>
|
||||
<n-grid :cols="12" :y-gap="6">
|
||||
<n-gi :span="6">
|
||||
<n-text :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']"
|
||||
:to="Number(result['当前价格'])"/>
|
||||
@@ -1813,6 +1814,9 @@ function searchStockReport(stockCode) {
|
||||
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday"/>
|
||||
</n-text>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<stock-spark-line :last-price="Number(result['当前价格'])" :open-price="Number(result['昨日收盘价'])" :stock-code="result['股票代码']" :stock-name="result['股票名称']" ></stock-spark-line>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
<n-grid :cols="2" :y-gap="4" :x-gap="4">
|
||||
<n-gi>
|
||||
|
||||
137
frontend/src/components/stockSparkLine.vue
Normal file
137
frontend/src/components/stockSparkLine.vue
Normal file
@@ -0,0 +1,137 @@
|
||||
<script setup>
|
||||
import {onMounted, onBeforeMount, ref, watchEffect} from "vue";
|
||||
import * as echarts from 'echarts';
|
||||
import {GetStockMinutePriceLineData} from "../../wailsjs/go/main/App"; // 如果您使用多个组件,请将此样式导入放在您的主文件中
|
||||
const {stockCode,stockName,lastPrice,openPrice,darkTheme} = defineProps({
|
||||
stockCode: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
stockName: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
lastPrice: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
openPrice: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
darkTheme: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
})
|
||||
|
||||
const chartRef=ref();
|
||||
|
||||
function setChartData(chart) {
|
||||
//console.log("setChartData")
|
||||
GetStockMinutePriceLineData(stockCode, stockName).then(result => {
|
||||
//console.log("GetStockMinutePriceLineData",result)
|
||||
const priceData = result.priceData
|
||||
let category = []
|
||||
let price = []
|
||||
let min = 0
|
||||
let max = 0
|
||||
for (let i = 0; i < priceData.length; i++) {
|
||||
category.push(priceData[i].time)
|
||||
price.push(priceData[i].price)
|
||||
if (min === 0 || min > priceData[i].price) {
|
||||
min = priceData[i].price
|
||||
}
|
||||
if (max < priceData[i].price) {
|
||||
max = priceData[i].price
|
||||
}
|
||||
}
|
||||
let option = {
|
||||
padding: [0, 0, 0, 0],
|
||||
grid: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
backgroundColor: '#6a7985'
|
||||
}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
show: false,
|
||||
type: 'category',
|
||||
data: category
|
||||
},
|
||||
yAxis: {
|
||||
show: false,
|
||||
type: 'value',
|
||||
min: (min).toFixed(2),
|
||||
max: (max).toFixed(2),
|
||||
minInterval: 0.01,
|
||||
},
|
||||
// visualMap: {
|
||||
// show: false,
|
||||
// type: 'piecewise',
|
||||
// pieces: [
|
||||
// {
|
||||
// min: Number(min),
|
||||
// max: Number(openPrice),
|
||||
// color: 'green'
|
||||
// },
|
||||
// {
|
||||
// min: Number(openPrice),
|
||||
// max: Number(max),
|
||||
// color: 'red'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
series: [
|
||||
{
|
||||
data: price,
|
||||
type: 'line',
|
||||
smooth: false,
|
||||
stack: '总量',
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
color: lastPrice > openPrice ? 'rgba(245, 0, 0, 1)' : 'rgb(6,251,10)'
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||
offset: 0,
|
||||
color: lastPrice > openPrice ? 'rgba(245, 0, 0, 1)' : 'rgba(6,251,10, 1)'
|
||||
}, {
|
||||
offset: 1,
|
||||
color: lastPrice > openPrice ? 'rgba(245, 0, 0, 0.25)' : 'rgba(6,251,10, 0.25)'
|
||||
}])
|
||||
},
|
||||
}
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
})
|
||||
}
|
||||
const chart =ref( null)
|
||||
|
||||
onMounted(() => {
|
||||
chart.value = echarts.init( document.getElementById('sparkLine'+stockCode));
|
||||
setChartData(chart.value);
|
||||
})
|
||||
|
||||
|
||||
watchEffect(() => {
|
||||
console.log(stockName,'lastPrice变化为:', lastPrice,lastPrice > openPrice)
|
||||
setChartData(chart.value);
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div style="height: 20px;width: 100%" :id="'sparkLine'+stockCode">
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,25 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {h} from 'vue'
|
||||
import {NTag,NImage} from 'naive-ui'
|
||||
import EmbeddedUrl from "./EmbeddedUrl.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-tabs type="line" animated>
|
||||
<n-tab-pane name="百度股市通" tab="百度股市通">
|
||||
<embedded-url url="https://gushitong.baidu.com" :height="'calc(100vh - 252px)'"/>
|
||||
<n-tab-pane name="选股通" tab="选股通">
|
||||
<embedded-url url="https://xuangutong.com.cn" :height="'calc(100vh - 252px)'"/>
|
||||
</n-tab-pane>
|
||||
<!-- <n-tab-pane name="百度股市通" tab="百度股市通">-->
|
||||
<!-- <embedded-url url="https://gushitong.baidu.com" :height="'calc(100vh - 252px)'"/>-->
|
||||
<!-- </n-tab-pane>-->
|
||||
<n-tab-pane name="东财大盘星图" tab="东财大盘星图">
|
||||
<embedded-url url="https://quote.eastmoney.com/stockhotmap/" :height="'calc(100vh - 252px)'"/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="TopHub" tab="TopHub(今日热榜)">
|
||||
<embedded-url url="https://tophub.today/c/finance" :height="'calc(100vh - 252px)'"/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="选股通" tab="选股通">
|
||||
<embedded-url url="https://xuangutong.com.cn" :height="'calc(100vh - 252px)'"/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="摸鱼" tab="摸鱼">
|
||||
<embedded-url url="https://996.ninja/" :height="'calc(100vh - 252px)'"/>
|
||||
</n-tab-pane>
|
||||
<!-- <n-tab-pane name="摸鱼" tab="摸鱼">-->
|
||||
<!-- <embedded-url url="https://996.ninja/" :height="'calc(100vh - 252px)'"/>-->
|
||||
<!-- </n-tab-pane>-->
|
||||
|
||||
|
||||
<n-tab-pane name="欢迎推荐更多有趣的财经网页" tab="欢迎推荐更多有趣的财经网页">
|
||||
|
||||
@@ -2,21 +2,22 @@ import {createMemoryHistory, createRouter, createWebHashHistory, createWebHistor
|
||||
|
||||
import stockView from '../components/stock.vue'
|
||||
import settingsView from '../components/settings.vue'
|
||||
import about from "../components/about.vue";
|
||||
import aboutView from "../components/about.vue";
|
||||
import fundView from "../components/fund.vue";
|
||||
import market from "../components/market.vue";
|
||||
import marketView from "../components/market.vue";
|
||||
|
||||
const routes = [
|
||||
{ path: '/', component: stockView,name: 'stock'},
|
||||
{ path: '/fund', component: fundView,name: 'fund' },
|
||||
{ path: '/settings', component: settingsView,name: 'settings' },
|
||||
{ path: '/about', component: about,name: 'about' },
|
||||
{ path: '/market', component: market,name: 'market' },
|
||||
{ path: '/about', component: aboutView,name: 'about' },
|
||||
{ path: '/market', component: marketView,name: 'market' },
|
||||
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
//history: createWebHistory(),
|
||||
history: createWebHashHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
|
||||
1
go.mod
1
go.mod
@@ -13,6 +13,7 @@ require (
|
||||
github.com/go-ego/gse v0.80.3
|
||||
github.com/go-resty/resty/v2 v2.16.2
|
||||
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf
|
||||
github.com/robertkrimen/otto v0.5.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/samber/lo v1.49.1
|
||||
|
||||
2
go.sum
2
go.sum
@@ -57,6 +57,8 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
|
||||
github.com/jackmordaunt/icns/v3 v3.0.1 h1:xxot6aNuGrU+lNgxz5I5H0qSeCjNKp8uTXB1j8D4S3o=
|
||||
github.com/jackmordaunt/icns/v3 v3.0.1/go.mod h1:5sHL59nqTd2ynTnowxB/MDQFhKNqkK8X687uKNygaSQ=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||
|
||||
Reference in New Issue
Block a user