mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
feat(frontend): 优化用户界面和功能
- 添加全屏切换功能 - 实现窗口隐藏和退出功能 - 新增设置菜单 - 优化股票信息展示界面 - 调整窗口大小和布局
This commit is contained in:
parent
88fb3ce94c
commit
b1a0e9575b
43
app.go
43
app.go
@ -177,6 +177,11 @@ func addStockFollowData(follow data.FollowedStock, stockData *data.StockInfo) {
|
||||
//昨日收盘价
|
||||
preClosePrice, _ := convertor.ToFloat(stockData.PreClose)
|
||||
|
||||
//当前价格依然为0 时 使用昨日收盘价为当前价格
|
||||
if price == 0 {
|
||||
price = preClosePrice
|
||||
}
|
||||
|
||||
//今日最高价
|
||||
highPrice, _ := convertor.ToFloat(stockData.High)
|
||||
if highPrice == 0 {
|
||||
@ -191,20 +196,34 @@ func addStockFollowData(follow data.FollowedStock, stockData *data.StockInfo) {
|
||||
//开盘价
|
||||
//openPrice, _ := convertor.ToFloat(stockData.Open)
|
||||
|
||||
stockData.ChangePrice = mathutil.RoundToFloat(price-preClosePrice, 2)
|
||||
stockData.ChangePercent = mathutil.RoundToFloat(mathutil.Div(price-preClosePrice, preClosePrice)*100, 3)
|
||||
stockData.HighRate = mathutil.RoundToFloat(mathutil.Div(highPrice-preClosePrice, preClosePrice)*100, 3)
|
||||
stockData.LowRate = mathutil.RoundToFloat(mathutil.Div(lowPrice-preClosePrice, preClosePrice)*100, 3)
|
||||
if price > 0 {
|
||||
stockData.ChangePrice = mathutil.RoundToFloat(price-preClosePrice, 2)
|
||||
stockData.ChangePercent = mathutil.RoundToFloat(mathutil.Div(price-preClosePrice, preClosePrice)*100, 3)
|
||||
}
|
||||
if highPrice > 0 {
|
||||
stockData.HighRate = mathutil.RoundToFloat(mathutil.Div(highPrice-preClosePrice, preClosePrice)*100, 3)
|
||||
}
|
||||
if lowPrice > 0 {
|
||||
stockData.LowRate = mathutil.RoundToFloat(mathutil.Div(lowPrice-preClosePrice, preClosePrice)*100, 3)
|
||||
}
|
||||
if follow.CostPrice > 0 && follow.Volume > 0 {
|
||||
stockData.Profit = mathutil.RoundToFloat(mathutil.Div(price-follow.CostPrice, follow.CostPrice)*100, 3)
|
||||
stockData.ProfitAmount = mathutil.RoundToFloat((price-follow.CostPrice)*float64(follow.Volume), 2)
|
||||
stockData.ProfitAmountToday = mathutil.RoundToFloat((price-preClosePrice)*float64(follow.Volume), 2)
|
||||
if price > 0 {
|
||||
stockData.Profit = mathutil.RoundToFloat(mathutil.Div(price-follow.CostPrice, follow.CostPrice)*100, 3)
|
||||
stockData.ProfitAmount = mathutil.RoundToFloat((price-follow.CostPrice)*float64(follow.Volume), 2)
|
||||
stockData.ProfitAmountToday = mathutil.RoundToFloat((price-preClosePrice)*float64(follow.Volume), 2)
|
||||
} else {
|
||||
//未开盘时当前价格为昨日收盘价
|
||||
stockData.Profit = mathutil.RoundToFloat(mathutil.Div(preClosePrice-follow.CostPrice, follow.CostPrice)*100, 3)
|
||||
stockData.ProfitAmount = mathutil.RoundToFloat((preClosePrice-follow.CostPrice)*float64(follow.Volume), 2)
|
||||
stockData.ProfitAmountToday = mathutil.RoundToFloat((preClosePrice-preClosePrice)*float64(follow.Volume), 2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//logger.SugaredLogger.Debugf("stockData:%+v", stockData)
|
||||
if follow.Price != price {
|
||||
if follow.Price != price && price > 0 {
|
||||
go db.Dao.Model(follow).Where("stock_code = ?", follow.StockCode).Updates(map[string]interface{}{
|
||||
"price": stockData.Price,
|
||||
"price": price,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -306,10 +325,8 @@ func (a *App) SendDingDingMessageByType(message string, stockCode string, msgTyp
|
||||
}
|
||||
stockInfo := &data.StockInfo{}
|
||||
db.Dao.Model(stockInfo).Where("code = ?", stockCode).First(stockInfo)
|
||||
if !data.NewAlertWindowsApi("go-stock消息通知", getMsgTypeName(msgType), GenNotificationMsg(stockInfo), "").SendNotification() {
|
||||
return data.NewDingDingAPI().SendDingDingMessage(message)
|
||||
}
|
||||
return "发送系统消息成功"
|
||||
go data.NewAlertWindowsApi("go-stock消息通知", getMsgTypeName(msgType), GenNotificationMsg(stockInfo), "").SendNotification()
|
||||
return data.NewDingDingAPI().SendDingDingMessage(message)
|
||||
}
|
||||
|
||||
func GenNotificationMsg(stockInfo *data.StockInfo) string {
|
||||
|
@ -295,14 +295,19 @@ func (receiver StockDataApi) GetStockCodeRealTimeData(StockCodes ...string) (*[]
|
||||
continue
|
||||
}
|
||||
stockInfos = append(stockInfos, *stockData)
|
||||
|
||||
go func() {
|
||||
var count int64
|
||||
db.Dao.Model(&StockInfo{}).Where("code = ?", stockData.Code).Count(&count)
|
||||
if count == 0 {
|
||||
db.Dao.Model(&StockInfo{}).Create(stockData)
|
||||
} else {
|
||||
db.Dao.Model(&StockInfo{}).Where("code = ?", stockData.Code).Updates(stockData)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
//var count int64
|
||||
//db.Dao.Model(&StockInfo{}).Where("code = ?", StockCode).Count(&count)
|
||||
//if count == 0 {
|
||||
// go db.Dao.Model(&StockInfo{}).Create(stockData)
|
||||
//} else {
|
||||
// go db.Dao.Model(&StockInfo{}).Where("code = ?", StockCode).Updates(stockData)
|
||||
//}
|
||||
|
||||
return &stockInfos, err
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ func TestParseFullSingleStockData(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewStockDataApi(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
stockDataApi := NewStockDataApi()
|
||||
datas, _ := stockDataApi.GetStockCodeRealTimeData("sh600859", "sh600745")
|
||||
for _, data := range *datas {
|
||||
|
22
frontend/package-lock.json
generated
22
frontend/package-lock.json
generated
@ -9,7 +9,8 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"vue": "^3.2.25"
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
@ -801,6 +802,11 @@
|
||||
"@vue/shared": "3.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/devtools-api": {
|
||||
"version": "6.6.4",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
|
||||
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
|
||||
@ -1241,6 +1247,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.0.tgz",
|
||||
"integrity": "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.6.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vueuc": {
|
||||
"version": "0.4.64",
|
||||
"resolved": "https://registry.npmmirror.com/vueuc/-/vueuc-0.4.64.tgz",
|
||||
|
@ -10,7 +10,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"vue": "^3.2.25"
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
|
@ -1 +1 @@
|
||||
fda5308055dfd8a9cbfbd89ea27276c4
|
||||
00b8e620dca5bab58d37996f0f350d0a
|
@ -1,13 +1,111 @@
|
||||
<script setup>
|
||||
import stockInfo from './components/stock.vue'
|
||||
import {ref} from "vue";
|
||||
import { darkTheme } from 'naive-ui'
|
||||
import {
|
||||
Quit,
|
||||
WindowFullscreen,
|
||||
WindowHide,
|
||||
WindowIsFullscreen,
|
||||
WindowUnfullscreen
|
||||
} from '../wailsjs/runtime'
|
||||
import {h, ref} from "vue";
|
||||
import {darkTheme, NIcon} from 'naive-ui'
|
||||
import {
|
||||
SettingsOutline,
|
||||
ReorderTwoOutline,
|
||||
ExpandOutline,
|
||||
RefreshOutline, PowerOutline,
|
||||
} from '@vicons/ionicons5'
|
||||
|
||||
const content = ref('数据来源于网络,仅供参考\n投资有风险,入市需谨慎')
|
||||
</script>
|
||||
const isFullscreen = ref(false)
|
||||
const activeKey = ref('stock')
|
||||
const containerRef= ref({})
|
||||
const menuOptions = ref([
|
||||
{
|
||||
label: '设置',
|
||||
key: 'settings',
|
||||
icon: renderIcon(SettingsOutline),
|
||||
children: [
|
||||
{
|
||||
type: 'group',
|
||||
label: '开发中',
|
||||
key: 'setting',
|
||||
children: [
|
||||
// {
|
||||
// label: '叙事者',
|
||||
// key: 'narrator',
|
||||
// icon: renderIcon(PersonIcon)
|
||||
// },
|
||||
// {
|
||||
// label: '羊男',
|
||||
// key: 'sheep-man',
|
||||
// icon: renderIcon(PersonIcon)
|
||||
// }
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: ()=> h("a", {
|
||||
href: '#',
|
||||
onClick: toggleFullscreen
|
||||
}, { default: () => '全屏' }),
|
||||
key: 'full',
|
||||
icon: renderIcon(ExpandOutline),
|
||||
},
|
||||
{
|
||||
label: ()=> h("a", {
|
||||
href: '#',
|
||||
onClick: WindowHide,
|
||||
}, { default: () => '隐藏到托盘区' }),
|
||||
key: 'hide',
|
||||
icon: renderIcon(ReorderTwoOutline),
|
||||
|
||||
},
|
||||
{
|
||||
label: () =>
|
||||
h(
|
||||
'a',
|
||||
{
|
||||
href: '/',
|
||||
target: '_self'
|
||||
},
|
||||
{ default: () => '刷新' }
|
||||
),
|
||||
key: 'stock',
|
||||
icon: renderIcon(RefreshOutline)
|
||||
},
|
||||
{
|
||||
label: ()=> h("a", {
|
||||
href: '#',
|
||||
onClick: Quit,
|
||||
}, { default: () => '退出程序' }),
|
||||
key: 'exit',
|
||||
icon: renderIcon(PowerOutline),
|
||||
},
|
||||
])
|
||||
function renderIcon(icon) {
|
||||
return () => h(NIcon, null, { default: () => h(icon) })
|
||||
}
|
||||
function toggleFullscreen(e) {
|
||||
console.log(e)
|
||||
WindowIsFullscreen().then((isFull) => {
|
||||
isFullscreen.value = isFull
|
||||
if (isFull) {
|
||||
WindowUnfullscreen()
|
||||
e.target.innerHTML = '全屏'
|
||||
} else {
|
||||
WindowFullscreen()
|
||||
e.target.innerHTML = '取消全屏'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<n-config-provider :theme="darkTheme">
|
||||
|
||||
|
||||
<n-config-provider :theme="darkTheme" ref="containerRef">
|
||||
<n-watermark
|
||||
:content="content"
|
||||
cross
|
||||
@ -21,10 +119,26 @@ const content = ref('数据来源于网络,仅供参考\n投资有风险,入市
|
||||
:rotate="-15"
|
||||
style="height: 100%"
|
||||
>
|
||||
|
||||
<n-flex justify="center">
|
||||
<n-message-provider >
|
||||
<n-modal-provider>
|
||||
<stockInfo/>
|
||||
<n-grid x-gap="12" :cols="1">
|
||||
|
||||
<n-gi>
|
||||
<stockInfo/>
|
||||
</n-gi>
|
||||
<n-gi style="position: sticky;bottom:0;z-index: 9999;">
|
||||
<n-card size="small">
|
||||
<n-menu style="font-size: 18px;"
|
||||
v-model:value="activeKey"
|
||||
mode="horizontal"
|
||||
:options="menuOptions"
|
||||
responsive
|
||||
/>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-modal-provider>
|
||||
</n-message-provider>
|
||||
</n-flex>
|
||||
|
@ -334,13 +334,13 @@ function SendMessage(result,type){
|
||||
let img='http://image.sinajs.cn/newchart/min/n/'+result["股票代码"]+'.gif'+"?t="+Date.now()
|
||||
let markdown="### go-stock ["+typeName+"]\n\n"+
|
||||
"### "+result["股票名称"]+"("+result["股票代码"]+")\n" +
|
||||
"- 当前价格: "+result["当前价格"]+" "+result.s+"\n" +
|
||||
"- 当前价格: "+result["当前价格"]+" "+result.changePercent+"%\n" +
|
||||
"- 最高价: "+result["今日最高价"]+" "+result.highRate+"\n" +
|
||||
"- 最低价: "+result["今日最低价"]+" "+result.lowRate+"\n" +
|
||||
"- 昨收价: "+result["昨日收盘价"]+"\n" +
|
||||
"- 今开价: "+result["今日开盘价"]+"\n" +
|
||||
"- 成本价: "+result.costPrice+" "+result.profit+"% "+result.profitAmount+" ¥\n" +
|
||||
"- 成本数量: "+result.volume+"股\n" +
|
||||
"- 成本数量: "+result.costVolume+"股\n" +
|
||||
"- 日期: "+result["日期"]+" "+result["时间"]+"\n\n"+
|
||||
"\n"
|
||||
let title=result["股票名称"]+"("+result["股票代码"]+") "+result["当前价格"]+" "+result.s
|
||||
@ -432,7 +432,7 @@ function getHeight() {
|
||||
</n-card >
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
<n-affix :trigger-bottom="getHeight()/2-10" style="left:0">
|
||||
<n-affix :trigger-bottom="15" style="right:0;z-index: 99990;">
|
||||
<!-- <n-card :bordered="false">-->
|
||||
<n-input-group>
|
||||
|
||||
@ -506,25 +506,5 @@ function getHeight() {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.result {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin: 1.5rem auto;
|
||||
}
|
||||
.input-box {
|
||||
text-align: center;
|
||||
}
|
||||
.input {
|
||||
width: 200px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.light-green {
|
||||
height: 108px;
|
||||
background-color: rgba(0, 128, 0, 0.12);
|
||||
}
|
||||
.green {
|
||||
height: 108px;
|
||||
background-color: rgba(0, 128, 0, 0.24);
|
||||
}
|
||||
</style>
|
||||
|
4
main.go
4
main.go
@ -82,14 +82,14 @@ func main() {
|
||||
err := wails.Run(&options.App{
|
||||
Title: "go-stock",
|
||||
Width: 1366,
|
||||
Height: 860,
|
||||
Height: 920,
|
||||
MinWidth: 1024,
|
||||
MinHeight: 768,
|
||||
MaxWidth: 1280,
|
||||
MaxHeight: 960,
|
||||
DisableResize: false,
|
||||
Fullscreen: false,
|
||||
Frameless: false,
|
||||
Frameless: true,
|
||||
StartHidden: false,
|
||||
HideWindowOnClose: false,
|
||||
BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
|
||||
|
Loading…
x
Reference in New Issue
Block a user