mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
添加成本设置
This commit is contained in:
parent
05c9aaeae5
commit
51cbcd52ba
4
app.go
4
app.go
@ -59,3 +59,7 @@ func (a *App) GetFollowList() []data.FollowedStock {
|
|||||||
func (a *App) GetStockList(key string) []data.StockBasic {
|
func (a *App) GetStockList(key string) []data.StockBasic {
|
||||||
return data.NewStockDataApi().GetStockList(key)
|
return data.NewStockDataApi().GetStockList(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) SetCostPriceAndVolume(stockCode string, price float64, volume int64) string {
|
||||||
|
return data.NewStockDataApi().SetCostPriceAndVolume(price, volume, stockCode)
|
||||||
|
}
|
||||||
|
@ -127,6 +127,8 @@ type StockBasic struct {
|
|||||||
type FollowedStock struct {
|
type FollowedStock struct {
|
||||||
StockCode string
|
StockCode string
|
||||||
Name string
|
Name string
|
||||||
|
Volume int64
|
||||||
|
CostPrice float64
|
||||||
Price float64
|
Price float64
|
||||||
PriceChange float64
|
PriceChange float64
|
||||||
ChangePercent float64
|
ChangePercent float64
|
||||||
@ -245,6 +247,15 @@ func (receiver StockDataApi) UnFollow(stockCode string) string {
|
|||||||
return "取消关注成功"
|
return "取消关注成功"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (receiver StockDataApi) SetCostPriceAndVolume(price float64, volume int64, stockCode string) string {
|
||||||
|
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", stockCode).Update("cost_price", price).Update("volume", volume).Error
|
||||||
|
if err != nil {
|
||||||
|
logger.SugaredLogger.Error(err.Error())
|
||||||
|
return "设置失败"
|
||||||
|
}
|
||||||
|
return "设置成功"
|
||||||
|
}
|
||||||
|
|
||||||
func (receiver StockDataApi) GetFollowList() []FollowedStock {
|
func (receiver StockDataApi) GetFollowList() []FollowedStock {
|
||||||
var result []FollowedStock
|
var result []FollowedStock
|
||||||
db.Dao.Model(&FollowedStock{}).Order("sort asc,time desc").Find(&result)
|
db.Dao.Model(&FollowedStock{}).Order("sort asc,time desc").Find(&result)
|
||||||
|
BIN
data/stock.db
BIN
data/stock.db
Binary file not shown.
2
frontend/package-lock.json
generated
2
frontend/package-lock.json
generated
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"naive-ui": "^2.32.1",
|
"naive-ui": "^2.40.3",
|
||||||
"vfonts": "^0.0.3",
|
"vfonts": "^0.0.3",
|
||||||
"vite": "5.4.6"
|
"vite": "5.4.6"
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"naive-ui": "^2.32.1",
|
"naive-ui": "^2.40.3",
|
||||||
"vfonts": "^0.0.3",
|
"vfonts": "^0.0.3",
|
||||||
"vite": "5.4.6"
|
"vite": "5.4.6"
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
576432f844039cfa1a8c66290cd327aa
|
9ce62efac1fed08499bbf20c8a5fd1b2
|
@ -21,7 +21,9 @@ const content = ref('数据来源于网络,仅供参考\n投资有风险,入市
|
|||||||
>
|
>
|
||||||
<n-flex justify="center">
|
<n-flex justify="center">
|
||||||
<n-message-provider >
|
<n-message-provider >
|
||||||
|
<n-modal-provider>
|
||||||
<stockInfo/>
|
<stockInfo/>
|
||||||
|
</n-modal-provider>
|
||||||
</n-message-provider>
|
</n-message-provider>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</n-watermark>
|
</n-watermark>
|
||||||
|
@ -1,16 +1,29 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
import {h, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
||||||
import {Greet,Follow,UnFollow,GetFollowList,GetStockList} from '../../wailsjs/go/main/App'
|
import {Greet, Follow, UnFollow, GetFollowList, GetStockList, SetCostPriceAndVolume} from '../../wailsjs/go/main/App'
|
||||||
import {NText, useMessage} from 'naive-ui'
|
import {NButton, NFlex, NForm, NFormItem, NInput, NInputNumber, NText, useMessage, useModal} from 'naive-ui'
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const modal = useModal()
|
||||||
|
|
||||||
const stocks=ref([])
|
const stocks=ref([])
|
||||||
const results=ref({})
|
const results=ref({})
|
||||||
const ticker=ref({})
|
const ticker=ref({})
|
||||||
const stockList=ref([])
|
const stockList=ref([])
|
||||||
|
const followList=ref([])
|
||||||
const options=ref([])
|
const options=ref([])
|
||||||
|
|
||||||
|
const formModel = ref({
|
||||||
|
costPrice: 0.000,
|
||||||
|
volume: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const form = h(NForm, { labelPlacement: 'left',model: formModel}, [
|
||||||
|
h(NFormItem, { label: '成本(元)',path:"costPrice" }, [h(NInputNumber, {path:"costPrice", onUpdateValue: updateCostPrice, clearable: true,precision:3, placeholder: '买入成本价(元)', })]),
|
||||||
|
h(NFormItem, { label: '数量(股)',path:"volume" }, [h(NInputNumber, {path:"volume",onUpdateValue: updateVolume, clearable: true,precision:0, placeholder: '买入股数,1手=100股', })]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
name: "",
|
name: "",
|
||||||
code: "",
|
code: "",
|
||||||
@ -28,12 +41,8 @@ onBeforeMount(()=>{
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
message.loading("Loading...")
|
|
||||||
console.log(`the component is now mounted.`)
|
|
||||||
GetFollowList().then(result => {
|
GetFollowList().then(result => {
|
||||||
|
followList.value = result
|
||||||
for (const followedStock of result) {
|
for (const followedStock of result) {
|
||||||
if (!stocks.value.includes(followedStock.StockCode)) {
|
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||||
stocks.value.push(followedStock.StockCode)
|
stocks.value.push(followedStock.StockCode)
|
||||||
@ -42,9 +51,11 @@ onMounted(() => {
|
|||||||
monitor()
|
monitor()
|
||||||
message.destroyAll
|
message.destroyAll
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
message.loading("Loading...")
|
||||||
|
console.log(`the component is now mounted.`)
|
||||||
|
|
||||||
ticker.value=setInterval(() => {
|
ticker.value=setInterval(() => {
|
||||||
if(isTradingTime()){
|
if(isTradingTime()){
|
||||||
@ -114,7 +125,7 @@ function getStockList(){
|
|||||||
|
|
||||||
function monitor() {
|
function monitor() {
|
||||||
for (let code of stocks.value) {
|
for (let code of stocks.value) {
|
||||||
console.log(code)
|
// console.log(code)
|
||||||
Greet(code).then(result => {
|
Greet(code).then(result => {
|
||||||
let s=(result["当前价格"]-result["昨日收盘价"])*100/result["昨日收盘价"]
|
let s=(result["当前价格"]-result["昨日收盘价"])*100/result["昨日收盘价"]
|
||||||
let roundedNum = s.toFixed(2); // 将数字转换为保留两位小数的字符串形式
|
let roundedNum = s.toFixed(2); // 将数字转换为保留两位小数的字符串形式
|
||||||
@ -129,6 +140,12 @@ function monitor() {
|
|||||||
result.type="default"
|
result.type="default"
|
||||||
result.color="#FFFFFF"
|
result.color="#FFFFFF"
|
||||||
}
|
}
|
||||||
|
let res= followList.value.filter(item => item.StockCode===code)
|
||||||
|
if (res.length>0) {
|
||||||
|
result.costPrice=res[0].CostPrice
|
||||||
|
result.volume=res[0].Volume
|
||||||
|
result.profit=((result["当前价格"]-result.costPrice)*100/result.costPrice).toFixed(3)
|
||||||
|
}
|
||||||
results.value[result["股票名称"]]=result
|
results.value[result["股票名称"]]=result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -138,22 +155,110 @@ function onSelect(item) {
|
|||||||
data.code=item.split(".")[1].toLowerCase()+item.split(".")[0]
|
data.code=item.split(".")[1].toLowerCase()+item.split(".")[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function search(code,name){
|
||||||
|
setTimeout(() => {
|
||||||
|
window.open("https://xueqiu.com/S/"+code)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
function updateCostPrice(v) {
|
||||||
|
console.log(formModel.value.costPrice)
|
||||||
|
formModel.value.costPrice=v
|
||||||
|
console.log(formModel.value.costPrice)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateVolume(v) {
|
||||||
|
console.log(formModel.value.volume)
|
||||||
|
formModel.value.volume=v
|
||||||
|
console.log(formModel.value.volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStock(code,name){
|
||||||
|
|
||||||
|
let res=followList.value.filter(item => item.StockCode===code)
|
||||||
|
console.log("res:",res)
|
||||||
|
formModel.value.volume=res[0].Volume
|
||||||
|
formModel.value.costPrice=res[0].CostPrice
|
||||||
|
|
||||||
|
const m = modal.create({
|
||||||
|
title: name,
|
||||||
|
preset: 'card',
|
||||||
|
style: {
|
||||||
|
width: '400px'
|
||||||
|
},
|
||||||
|
content: () => form,
|
||||||
|
footer: () =>
|
||||||
|
h(NFlex, { justify: 'center' },[
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{size:'small', type: 'primary', onClick: () =>updateCostPriceAndVolume(m,code,formModel.value.costPrice,formModel.value.volume) },
|
||||||
|
() => '保存'
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{ size:'small', type: 'warning', onClick: () => m.destroy() },
|
||||||
|
() => '关闭'
|
||||||
|
),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function updateCostPriceAndVolume(m,code,price,volume){
|
||||||
|
console.log(code,price,volume)
|
||||||
|
SetCostPriceAndVolume(code,price,volume).then(result => {
|
||||||
|
message.success(result)
|
||||||
|
m.destroy()
|
||||||
|
GetFollowList().then(result => {
|
||||||
|
followList.value = result
|
||||||
|
for (const followedStock of result) {
|
||||||
|
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||||
|
stocks.value.push(followedStock.StockCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
monitor()
|
||||||
|
message.destroyAll
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-grid x-gap="12" :cols="4" :y-gap="12">
|
<n-grid :x-gap="8" :cols="3" :y-gap="8">
|
||||||
<n-gi v-for="result in results" >
|
<n-gi v-for="result in results" >
|
||||||
<n-card :data-code="result['股票代码']" :bordered="false" :title="result['股票名称']" :content-style="'font-size: 16px;'" closable @close="removeMonitor(result['股票代码'],result['股票名称'])">
|
<n-card size="small" :data-code="result['股票代码']" :bordered="false" :title="result['股票名称']" :content-style="'font-size: 18px;'" closable @close="removeMonitor(result['股票代码'],result['股票名称'])">
|
||||||
<n-text :type="result.type" >{{result["当前价格"]}}</n-text><n-text style="padding-left: 10px;" :type="result.type">{{ result.s}}</n-text>
|
<n-grid :cols="1" :y-gap="6">
|
||||||
<template #footer>
|
<n-gi>
|
||||||
<n-text :type="'info'">{{"今开: "+result["今日开盘价"]}}</n-text><br>
|
<n-text :type="result.type" >{{result["当前价格"]}}</n-text><n-text style="padding-left: 10px;" :type="result.type">{{ result.s}}</n-text>
|
||||||
<n-text :type="'info'">{{"昨收: "+result["昨日收盘价"]}}</n-text>
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
<n-grid :cols="2" :y-gap="4" :x-gap="4" :item-style="'font-size: 14px;'">
|
||||||
|
<n-gi>
|
||||||
|
<n-text :type="'info'">{{"最高 "+result["今日最高价"]}}</n-text>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-text :type="'info'">{{"最低 "+result["今日最低价"]}}</n-text>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-text :type="'info'">{{"昨收 "+result["昨日收盘价"]}}</n-text>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-text :type="'info'">{{"今开 "+result["今日开盘价"]}}</n-text>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
<template #header-extra>
|
||||||
|
<n-tag size="small" v-if="result.volume>0" :type="result.type">{{result.volume+"股"}}</n-tag>
|
||||||
|
</template>
|
||||||
|
<template #action>
|
||||||
|
<n-flex justify="space-between">
|
||||||
|
<n-tag size="small" v-if="result.costPrice>0" :type="result.type">{{"成本:"+result.costPrice+" "+result.profit+"%"}}</n-tag>
|
||||||
|
<n-button size="tiny" type="info" @click="setStock(result['股票代码'],result['股票名称'])"> 设置 </n-button>
|
||||||
|
<n-button size="tiny" type="warning" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
||||||
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
</n-card >
|
</n-card >
|
||||||
</n-gi>
|
</n-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
|
|
||||||
|
|
||||||
<n-auto-complete v-model:value="data.name" type="text"
|
<n-auto-complete v-model:value="data.name" type="text"
|
||||||
:input-props="{
|
:input-props="{
|
||||||
autocomplete: 'disabled',
|
autocomplete: 'disabled',
|
||||||
@ -162,8 +267,6 @@ function onSelect(item) {
|
|||||||
placeholder="股票名称或者代码"
|
placeholder="股票名称或者代码"
|
||||||
clearable class="input" @input="getStockList" :on-select="onSelect"/>
|
clearable class="input" @input="getStockList" :on-select="onSelect"/>
|
||||||
<n-button type="info" @click="AddStock"> 添加 </n-button>
|
<n-button type="info" @click="AddStock"> 添加 </n-button>
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
2
frontend/wailsjs/go/main/App.d.ts
vendored
2
frontend/wailsjs/go/main/App.d.ts
vendored
@ -10,4 +10,6 @@ export function GetStockList(arg1:string):Promise<Array<data.StockBasic>>;
|
|||||||
|
|
||||||
export function Greet(arg1:string):Promise<data.StockInfo>;
|
export function Greet(arg1:string):Promise<data.StockInfo>;
|
||||||
|
|
||||||
|
export function SetCostPriceAndVolume(arg1:string,arg2:number,arg3:number):Promise<string>;
|
||||||
|
|
||||||
export function UnFollow(arg1:string):Promise<string>;
|
export function UnFollow(arg1:string):Promise<string>;
|
||||||
|
@ -18,6 +18,10 @@ export function Greet(arg1) {
|
|||||||
return window['go']['main']['App']['Greet'](arg1);
|
return window['go']['main']['App']['Greet'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SetCostPriceAndVolume(arg1, arg2, arg3) {
|
||||||
|
return window['go']['main']['App']['SetCostPriceAndVolume'](arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
export function UnFollow(arg1) {
|
export function UnFollow(arg1) {
|
||||||
return window['go']['main']['App']['UnFollow'](arg1);
|
return window['go']['main']['App']['UnFollow'](arg1);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ export namespace data {
|
|||||||
export class FollowedStock {
|
export class FollowedStock {
|
||||||
StockCode: string;
|
StockCode: string;
|
||||||
Name: string;
|
Name: string;
|
||||||
|
Volume: number;
|
||||||
|
CostPrice: number;
|
||||||
Price: number;
|
Price: number;
|
||||||
PriceChange: number;
|
PriceChange: number;
|
||||||
ChangePercent: number;
|
ChangePercent: number;
|
||||||
@ -18,6 +20,8 @@ export namespace data {
|
|||||||
if ('string' === typeof source) source = JSON.parse(source);
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
this.StockCode = source["StockCode"];
|
this.StockCode = source["StockCode"];
|
||||||
this.Name = source["Name"];
|
this.Name = source["Name"];
|
||||||
|
this.Volume = source["Volume"];
|
||||||
|
this.CostPrice = source["CostPrice"];
|
||||||
this.Price = source["Price"];
|
this.Price = source["Price"];
|
||||||
this.PriceChange = source["PriceChange"];
|
this.PriceChange = source["PriceChange"];
|
||||||
this.ChangePercent = source["ChangePercent"];
|
this.ChangePercent = source["ChangePercent"];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user