mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
22b4fcdffb
@ -400,7 +400,13 @@ func (receiver StockDataApi) Follow(stockCode string) string {
|
||||
logger.SugaredLogger.Error(err)
|
||||
return "关注失败"
|
||||
}
|
||||
|
||||
if strings.HasPrefix(stockCode, "us") {
|
||||
stockCode = strings.Replace(stockCode, "us", "gb_", 1)
|
||||
}
|
||||
if strings.HasPrefix(stockCode, "US") {
|
||||
stockCode = strings.Replace(stockCode, "US", "gb_", 1)
|
||||
}
|
||||
stockCode = strings.ToLower(stockCode)
|
||||
maxSort := int64(0)
|
||||
db.Dao.Model(&FollowedStock{}).Raw("select max(sort) as sort from followed_stock").Scan(&maxSort)
|
||||
|
||||
@ -463,15 +469,64 @@ func (receiver StockDataApi) SetAlarmChangePercent(val, alarmPrice float64, stoc
|
||||
return "设置成功"
|
||||
}
|
||||
|
||||
func (receiver StockDataApi) SetStockSort(sort int64, stockCode string) {
|
||||
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||
stockCode = strings.ToLower(stockCode)
|
||||
stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||
func (receiver StockDataApi) SetStockSort(newSort int64, stockCode string) {
|
||||
//if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||
// stockCode = strings.ToLower(stockCode)
|
||||
// stockCode = strings.Replace(stockCode, "gb_", "us", 1)
|
||||
//}
|
||||
|
||||
// 获取当前排序值
|
||||
var currentStock FollowedStock
|
||||
if err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", strings.ToLower(stockCode)).First(¤tStock).Error; err != nil {
|
||||
logger.SugaredLogger.Error("找不到当前股票: ", err.Error())
|
||||
return
|
||||
}
|
||||
err := db.Dao.Model(&FollowedStock{}).Where("stock_code = ?", strings.ToLower(stockCode)).Update("sort", sort).Error
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Error(err.Error())
|
||||
|
||||
oldSort := currentStock.Sort
|
||||
|
||||
// 如果排序值没有变化,直接返回
|
||||
if oldSort == newSort {
|
||||
return
|
||||
}
|
||||
// 检查新排序位置是否被占用
|
||||
var count int64
|
||||
if err := db.Dao.Model(&FollowedStock{}).Where("sort = ?", newSort).Count(&count).Error; err != nil {
|
||||
logger.SugaredLogger.Error("检查新排序位置被占用失败: ", err.Error())
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
// 新位置未被占用,直接更新当前记录
|
||||
if err := db.Dao.Model(&FollowedStock{}).
|
||||
Where("stock_code = ?", strings.ToLower(stockCode)).
|
||||
Update("sort", newSort).Error; err != nil {
|
||||
logger.SugaredLogger.Error("更新排序位置失败: ", err.Error())
|
||||
}
|
||||
} else {
|
||||
// 新位置已被占用,需要移动其他记录
|
||||
if newSort < oldSort {
|
||||
// 向前移动:将中间记录向后移动
|
||||
if err := db.Dao.Model(&FollowedStock{}).
|
||||
Where("sort >= ? AND sort < ?", newSort, oldSort).
|
||||
Update("sort", gorm.Expr("sort + 1")).Error; err != nil {
|
||||
logger.SugaredLogger.Error("向前排序更新失败: ", err.Error())
|
||||
}
|
||||
} else {
|
||||
// 向后移动:将中间记录向前移动
|
||||
if err := db.Dao.Model(&FollowedStock{}).
|
||||
Where("sort > ? AND sort <= ?", oldSort, newSort).
|
||||
Update("sort", gorm.Expr("sort - 1")).Error; err != nil {
|
||||
logger.SugaredLogger.Error("向后排序更新失败: ", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 更新目标记录的排序
|
||||
if err := db.Dao.Model(&FollowedStock{}).
|
||||
Where("stock_code = ?", strings.ToLower(stockCode)).
|
||||
Update("sort", newSort).Error; err != nil {
|
||||
logger.SugaredLogger.Error("更新股票排序失败: ", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
func (receiver StockDataApi) SetStockAICron(cron string, stockCode string) {
|
||||
if strutil.HasPrefixAny(stockCode, []string{"gb_"}) {
|
||||
|
@ -2,28 +2,31 @@
|
||||
import {computed, h, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
|
||||
import * as echarts from 'echarts';
|
||||
import {
|
||||
AddGroup,
|
||||
AddStockGroup,
|
||||
Follow,
|
||||
GetAIResponseResult,
|
||||
GetConfig,
|
||||
GetFollowList,
|
||||
GetGroupList,
|
||||
GetPromptTemplates,
|
||||
GetStockKLine,
|
||||
GetStockList,
|
||||
GetStockMinutePriceLineData,
|
||||
GetVersionInfo,
|
||||
Greet,
|
||||
NewChatStream,
|
||||
RemoveGroup,
|
||||
RemoveStockGroup,
|
||||
SaveAIResponseResult,
|
||||
SaveAsMarkdown,
|
||||
SendDingDingMessageByType,
|
||||
SetAlarmChangePercent,
|
||||
SetCostPriceAndVolume,
|
||||
SetStockSort,
|
||||
UnFollow,
|
||||
ShareAnalysis,
|
||||
SaveAsMarkdown,
|
||||
GetPromptTemplates,
|
||||
SetStockAICron,
|
||||
AddGroup,
|
||||
GetGroupList,
|
||||
AddStockGroup,
|
||||
RemoveStockGroup, RemoveGroup, GetStockKLine, GetStockMinutePriceLineData
|
||||
SetStockSort,
|
||||
ShareAnalysis,
|
||||
UnFollow
|
||||
} from '../../wailsjs/go/main/App'
|
||||
import {
|
||||
NAvatar,
|
||||
@ -35,7 +38,6 @@ import {
|
||||
NText,
|
||||
useDialog,
|
||||
useMessage,
|
||||
useModal,
|
||||
useNotification
|
||||
} from 'naive-ui'
|
||||
import {
|
||||
@ -46,11 +48,8 @@ import {
|
||||
WindowReload,
|
||||
WindowUnfullscreen
|
||||
} from '../../wailsjs/runtime'
|
||||
import {
|
||||
Add,
|
||||
ChatboxOutline,
|
||||
} from '@vicons/ionicons5'
|
||||
import {MdPreview,MdEditor } from 'md-editor-v3';
|
||||
import {Add, ChatboxOutline,} from '@vicons/ionicons5'
|
||||
import {MdEditor, MdPreview} from 'md-editor-v3';
|
||||
// preview.css相比style.css少了编辑器那部分样式
|
||||
//import 'md-editor-v3/lib/preview.css';
|
||||
import 'md-editor-v3/lib/style.css';
|
||||
@ -61,9 +60,10 @@ import html2canvas from "html2canvas";
|
||||
import {asBlob} from 'html-docx-js-typescript';
|
||||
|
||||
import vueDanmaku from 'vue3-danmaku'
|
||||
import {keys, pad, padStart} from "lodash";
|
||||
import {keys, padStart} from "lodash";
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import MoneyTrend from "./moneyTrend.vue";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
@ -139,7 +139,6 @@ const feishiInterval= ref(null)
|
||||
const currentGroupId = ref(0)
|
||||
|
||||
|
||||
|
||||
const theme = computed(() => {
|
||||
return data.darkTheme ? 'dark' : 'light'
|
||||
})
|
||||
@ -151,9 +150,7 @@ const danmakuColor = computed(()=> {
|
||||
const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/master/build/appicon.png');
|
||||
|
||||
const sortedResults = computed(() => {
|
||||
////console.log("computed",sortedResults.value)
|
||||
const sortedKeys = keys(results.value).sort();
|
||||
////console.log("sortedKeys",sortedKeys)
|
||||
const sortedObject = {};
|
||||
sortedKeys.forEach(key => {
|
||||
sortedObject[key] = results.value[key];
|
||||
@ -215,14 +212,6 @@ onBeforeMount(()=>{
|
||||
|
||||
onMounted(() => {
|
||||
message.loading("Loading...")
|
||||
// //console.log(`the component is now mounted.`)
|
||||
|
||||
// ticker.value=setInterval(() => {
|
||||
// if(isTradingTime()){
|
||||
// //monitor()
|
||||
// //data.fenshiURL='http://image.sinajs.cn/newchart/min/n/'+data.code+'.gif'+"?t="+Date.now()
|
||||
// }
|
||||
// }, 3500)
|
||||
|
||||
GetFollowList(currentGroupId.value).then(result => {
|
||||
|
||||
@ -232,7 +221,6 @@ onMounted(() => {
|
||||
followedStock.StockCode = "gb_" + followedStock.StockCode.replace("us", "").toLowerCase()
|
||||
}
|
||||
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||
////console.log("followList",followedStock.StockCode)
|
||||
stocks.value.push(followedStock.StockCode)
|
||||
}
|
||||
}
|
||||
@ -314,17 +302,6 @@ EventsOn("stock_price",(data)=>{
|
||||
EventsOn("refreshFollowList", (data) => {
|
||||
|
||||
WindowReload()
|
||||
// message.loading("refresh...")
|
||||
// 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
|
||||
// })
|
||||
})
|
||||
|
||||
EventsOn("newChatStream", async (msg) => {
|
||||
@ -457,6 +434,7 @@ function AddStock(){
|
||||
if (!stocks.value.includes(data.code)) {
|
||||
Follow(data.code).then(result => {
|
||||
if (result === "关注成功") {
|
||||
data.code= "gb_" + data.code.replace("us", "").toLowerCase()
|
||||
stocks.value.push(data.code)
|
||||
message.success(result)
|
||||
GetFollowList(currentGroupId.value).then(result => {
|
||||
@ -473,7 +451,6 @@ function AddStock(){
|
||||
}
|
||||
|
||||
|
||||
|
||||
function removeMonitor(code, name, key) {
|
||||
//console.log("removeMonitor",name,code,key)
|
||||
stocks.value.splice(stocks.value.indexOf(code), 1)
|
||||
@ -499,7 +476,6 @@ function SendDanmu(){
|
||||
function getStockList(value) {
|
||||
|
||||
|
||||
|
||||
// //console.log("getStockList",value)
|
||||
let result;
|
||||
result = stockList.value.filter(item => item.name.includes(value) || item.ts_code.includes(value))
|
||||
@ -524,8 +500,6 @@ function getStockList(value){
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function blinkBorder(findId) {
|
||||
@ -587,13 +561,16 @@ async function updateData(result) {
|
||||
}
|
||||
|
||||
// result.key=result.sort
|
||||
results.value = Object.fromEntries(
|
||||
Object.entries(results.value).filter(
|
||||
([key]) => !key.includes(result["股票代码"])
|
||||
));
|
||||
|
||||
result.key = GetSortKey(result.sort, result["股票代码"])
|
||||
results.value[GetSortKey(result.sort,result["股票代码"])]=result
|
||||
results.value[result.key] = result
|
||||
if (!stocks.value.includes(result["股票代码"])) {
|
||||
delete results.value[result.key]
|
||||
}
|
||||
|
||||
////console.log("updateData",result)
|
||||
}
|
||||
|
||||
|
||||
@ -602,7 +579,7 @@ async function monitor() {
|
||||
showPopover.value = true
|
||||
}
|
||||
for (let code of stocks.value) {
|
||||
// //console.log(code)
|
||||
|
||||
Greet(code).then(result => {
|
||||
updateData(result)
|
||||
})
|
||||
@ -612,7 +589,6 @@ async function monitor() {
|
||||
|
||||
function GetSortKey(sort, code) {
|
||||
let sortKey = padStart(sort, 8, '0') + "_" + code
|
||||
////console.log("GetSortKey:",sortKey)
|
||||
return sortKey
|
||||
}
|
||||
|
||||
@ -638,6 +614,7 @@ function search(code,name){
|
||||
//window.open("https://www.iwencai.com/chat/?question="+code)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
function setStock(code, name) {
|
||||
let res = followList.value.filter(item => item.StockCode === code)
|
||||
////console.log("res:",res)
|
||||
@ -651,10 +628,12 @@ function setStock(code,name){
|
||||
formModel.value.cron = res[0].Cron
|
||||
modalShow.value = true
|
||||
}
|
||||
|
||||
function clearFeishi() {
|
||||
//console.log("clearFeishi")
|
||||
clearInterval(feishiInterval.value)
|
||||
}
|
||||
|
||||
function showFsChart(code, name) {
|
||||
data.name = name
|
||||
data.code = code
|
||||
@ -921,6 +900,7 @@ function calculateMA(dayCount,values) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function handleKLine() {
|
||||
GetStockKLine(data.code, data.name, 365).then(result => {
|
||||
//console.log("GetStockKLine",result)
|
||||
@ -1246,6 +1226,7 @@ function handleKLine(){
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function showMoney(code, name) {
|
||||
data.code = code
|
||||
data.name = name
|
||||
@ -1268,10 +1249,7 @@ function showK(code,name){
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function updateCostPriceAndVolumeNew(code, price, volume, alarm, formModel) {
|
||||
|
||||
if (formModel.sort) {
|
||||
SetStockSort(formModel.sort, code).then(result => {
|
||||
//message.success(result)
|
||||
@ -1293,6 +1271,7 @@ function updateCostPriceAndVolumeNew(code,price,volume,alarm,formModel){
|
||||
message.success(result)
|
||||
GetFollowList(currentGroupId.value).then(result => {
|
||||
followList.value = result
|
||||
stocks.value = []
|
||||
for (const followedStock of result) {
|
||||
if (!stocks.value.includes(followedStock.StockCode)) {
|
||||
stocks.value.push(followedStock.StockCode)
|
||||
@ -1344,6 +1323,7 @@ function SendMessage(result,type){
|
||||
// SendDingDingMessage(msg,result["股票代码"])
|
||||
SendDingDingMessageByType(msg, result["股票代码"], type)
|
||||
}
|
||||
|
||||
function aiReCheckStock(stock, stockCode) {
|
||||
data.modelName = ""
|
||||
data.airesult = ""
|
||||
@ -1360,6 +1340,7 @@ function aiReCheckStock(stock,stockCode) {
|
||||
//message.info("sysPromptId:"+data.sysPromptId)
|
||||
NewChatStream(stock, stockCode, data.question, data.sysPromptId)
|
||||
}
|
||||
|
||||
function aiCheckStock(stock, stockCode) {
|
||||
GetAIResponseResult(stockCode).then(result => {
|
||||
if (result.content) {
|
||||
@ -1397,8 +1378,7 @@ function aiCheckStock(stock,stockCode){
|
||||
}
|
||||
|
||||
function getTypeName(type) {
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case 1:
|
||||
return "涨跌报警"
|
||||
case 2:
|
||||
@ -1461,11 +1441,13 @@ async function copyToClipboard() {
|
||||
message.error('复制失败: ' + err);
|
||||
}
|
||||
}
|
||||
|
||||
function saveAsMarkdown() {
|
||||
SaveAsMarkdown(data.code, data.name).then(result => {
|
||||
message.success(result)
|
||||
})
|
||||
}
|
||||
|
||||
function saveAsMarkdown_old() {
|
||||
const blob = new Blob([data.airesult], {type: 'text/markdown;charset=utf-8'});
|
||||
const link = document.createElement('a');
|
||||
@ -1475,6 +1457,7 @@ function saveAsMarkdown_old() {
|
||||
URL.revokeObjectURL(link.href);
|
||||
link.remove()
|
||||
}
|
||||
|
||||
function getHtml(ref) {
|
||||
if (ref.value) {
|
||||
// 获取 MdPreview 组件的根元素
|
||||
@ -1539,14 +1522,17 @@ function share(code,name){
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const addTabModel = ref({
|
||||
name: '',
|
||||
sort: 1,
|
||||
})
|
||||
const addTabPane = ref(false)
|
||||
|
||||
function addTab() {
|
||||
addTabPane.value = true
|
||||
}
|
||||
|
||||
function saveTabPane() {
|
||||
AddGroup(addTabModel.value).then(result => {
|
||||
message.info(result)
|
||||
@ -1556,6 +1542,7 @@ function saveTabPane(){
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function AddStockGroupInfo(groupId, code, name) {
|
||||
if (code.startsWith("gb_")) {
|
||||
code = "us" + code.replace("gb_", "").toLowerCase()
|
||||
@ -1568,11 +1555,11 @@ function AddStockGroupInfo(groupId,code,name){
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function updateTab(name) {
|
||||
currentGroupId.value = Number(name)
|
||||
GetFollowList(currentGroupId.value).then(result => {
|
||||
stocks.value = []
|
||||
//console.log("GetFollowList",result)
|
||||
followList.value = result
|
||||
for (const followedStock of result) {
|
||||
if (followedStock.StockCode.startsWith("us")) {
|
||||
@ -1585,6 +1572,7 @@ function updateTab(name){
|
||||
message.destroyAll()
|
||||
})
|
||||
}
|
||||
|
||||
function delTab(name) {
|
||||
let infos = groupList.value = groupList.value.filter(item => item.ID === Number(name))
|
||||
dialog.create({
|
||||
@ -1603,6 +1591,7 @@ function delTab(name){
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function delStockGroup(code, name, groupId) {
|
||||
RemoveStockGroup(code, name, groupId).then(result => {
|
||||
updateTab(groupId)
|
||||
@ -1619,6 +1608,7 @@ function searchNotice(stockCode){
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function searchStockReport(stockCode) {
|
||||
router.push({
|
||||
name: 'market',
|
||||
@ -1631,26 +1621,35 @@ function searchStockReport(stockCode){
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<vue-danmaku v-model:danmus="danmus" useSlot style="height:100px; width:100%;z-index: 9;position:absolute; top: 400px; pointer-events: none;" >
|
||||
<vue-danmaku v-model:danmus="danmus" useSlot
|
||||
style="height:100px; width:100%;z-index: 9;position:absolute; top: 400px; pointer-events: none;">
|
||||
<template v-slot:dm="{ index, danmu }">
|
||||
<n-gradient-text type="info">
|
||||
<n-icon :component="ChatboxOutline"/>{{ danmu }}
|
||||
<n-icon :component="ChatboxOutline"/>
|
||||
{{ danmu }}
|
||||
</n-gradient-text>
|
||||
</template>
|
||||
</vue-danmaku>
|
||||
<n-tabs type="card" style="--wails-draggable:drag" animated addable :data-currentGroupId="currentGroupId" :value="currentGroupId" @add="addTab" @update-value="updateTab" placement="top" @close="(key)=>{delTab(key)}">
|
||||
<n-tabs type="card" style="--wails-draggable:drag" animated addable :data-currentGroupId="currentGroupId"
|
||||
:value="currentGroupId" @add="addTab" @update-value="updateTab" placement="top" @close="(key)=>{delTab(key)}">
|
||||
<n-tab-pane :name="0" :tab="'全部'">
|
||||
<n-grid :x-gap="8" :cols="3" :y-gap="8">
|
||||
<n-gi :id="result['股票代码']+'_gi'" v-for="result in sortedResults" style="margin-left: 2px;">
|
||||
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true" :title="result['股票名称']" :closable="false" @close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
<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-text :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']" :to="Number(result['当前价格'])" />
|
||||
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">({{result['盘前盘后']}} {{result['盘前盘后涨跌幅']}}%)</n-tag>
|
||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']"
|
||||
:to="Number(result['当前价格'])"/>
|
||||
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">
|
||||
({{ result['盘前盘后'] }} {{ result['盘前盘后涨跌幅'] }}%)
|
||||
</n-tag>
|
||||
</n-text>
|
||||
<n-text style="padding-left: 10px;" :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent" />%
|
||||
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent"/>
|
||||
%
|
||||
</n-text>
|
||||
<n-text size="small" v-if="result.costVolume>0" :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday"/>
|
||||
@ -1720,10 +1719,12 @@ function searchStockReport(stockCode){
|
||||
<template #header-extra>
|
||||
|
||||
<n-tag size="small" :bordered="false">{{ result['股票代码'] }}</n-tag>
|
||||
<n-button size="tiny" secondary type="primary" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
<n-button size="tiny" secondary type="primary"
|
||||
@click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
取消关注
|
||||
</n-button>
|
||||
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning" @click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
||||
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning"
|
||||
@click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
||||
AI分析
|
||||
</n-button>
|
||||
|
||||
@ -1732,20 +1733,33 @@ function searchStockReport(stockCode){
|
||||
<n-flex justify="center">
|
||||
<n-text :type="'info'">{{ result["日期"] + " " + result["时间"] }}</n-text>
|
||||
<n-tag size="small" v-if="result.volume>0" :type="result.profitType">{{ result.volume + "股" }}</n-tag>
|
||||
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">{{"成本:"+result.costPrice+"*"+result.costVolume+" "+result.profit+"%"+" ( "+result.profitAmount+" ¥ )"}}</n-tag>
|
||||
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">
|
||||
{{ "成本:" + result.costPrice + "*" + result.costVolume + " " + result.profit + "%" + " ( " + result.profitAmount + " ¥ )" }}
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
</template>
|
||||
<template #action>
|
||||
<n-flex justify="left">
|
||||
<n-button size="tiny" type="warning" @click="setStock(result['股票代码'],result['股票名称'])"> 成本 </n-button>
|
||||
<n-button size="tiny" type="error" @click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时 </n-button>
|
||||
<n-button size="tiny" type="warning" @click="setStock(result['股票代码'],result['股票名称'])"> 成本
|
||||
</n-button>
|
||||
<n-button size="tiny" type="error"
|
||||
@click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时
|
||||
</n-button>
|
||||
<n-button size="tiny" type="error" @click="showK(result['股票代码'],result['股票名称'])"> 日K</n-button>
|
||||
<n-button size="tiny" type="error" v-if="result['买一报价']>0" @click="showMoney(result['股票代码'],result['股票名称'])"> 资金 </n-button>
|
||||
<n-button size="tiny" type="success" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success" @click="searchNotice(result['股票代码'])"> 公告 </n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success" @click="searchStockReport(result['股票代码'])"> 研报 </n-button>
|
||||
<n-button size="tiny" type="error" v-if="result['买一报价']>0"
|
||||
@click="showMoney(result['股票代码'],result['股票名称'])"> 资金
|
||||
</n-button>
|
||||
<n-button size="tiny" type="success" @click="search(result['股票代码'],result['股票名称'])"> 详情
|
||||
</n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
||||
@click="searchNotice(result['股票代码'])"> 公告
|
||||
</n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
||||
@click="searchStockReport(result['股票代码'])"> 研报
|
||||
</n-button>
|
||||
<n-flex justify="right">
|
||||
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name" @select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
||||
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name"
|
||||
@select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
||||
<n-button type="warning" size="tiny">设置分组</n-button>
|
||||
</n-dropdown>
|
||||
</n-flex>
|
||||
@ -1758,15 +1772,21 @@ function searchStockReport(stockCode){
|
||||
<n-tab-pane closable v-for="group in groupList" :group-id="group.ID" :name="group.ID" :tab="group.name">
|
||||
<n-grid :x-gap="8" :cols="3" :y-gap="8">
|
||||
<n-gi :id="result['股票代码']+'_gi'" v-for="result in groupResults" style="margin-left: 2px;">
|
||||
<n-card :data-sort="result.sort" :id="result['股票代码']" :data-code="result['股票代码']" :bordered="true" :title="result['股票名称']" :closable="false" @close="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
<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-text :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']" :to="Number(result['当前价格'])" />
|
||||
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">({{result['盘前盘后']}} {{result['盘前盘后涨跌幅']}}%)</n-tag>
|
||||
<n-number-animation :duration="1000" :precision="2" :from="result['上次当前价格']"
|
||||
:to="Number(result['当前价格'])"/>
|
||||
<n-tag size="small" :type="result.type" :bordered="false" v-if="result['盘前盘后']>0">
|
||||
({{ result['盘前盘后'] }} {{ result['盘前盘后涨跌幅'] }}%)
|
||||
</n-tag>
|
||||
</n-text>
|
||||
<n-text style="padding-left: 10px;" :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent" />%
|
||||
<n-number-animation :duration="1000" :precision="3" :from="0" :to="result.changePercent"/>
|
||||
%
|
||||
</n-text>
|
||||
<n-text size="small" v-if="result.costVolume>0" :type="result.type">
|
||||
<n-number-animation :duration="1000" :precision="2" :from="0" :to="result.profitAmountToday"/>
|
||||
@ -1836,32 +1856,49 @@ function searchStockReport(stockCode){
|
||||
<template #header-extra>
|
||||
|
||||
<n-tag size="small" :bordered="false">{{ result['股票代码'] }}</n-tag>
|
||||
<n-button size="tiny" secondary type="primary" @click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
<n-button size="tiny" secondary type="primary"
|
||||
@click="removeMonitor(result['股票代码'],result['股票名称'],result.key)">
|
||||
取消关注
|
||||
</n-button>
|
||||
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning" @click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
||||
<n-button size="tiny" v-if="data.openAiEnable" secondary type="warning"
|
||||
@click="aiCheckStock(result['股票名称'],result['股票代码'])">
|
||||
AI分析
|
||||
</n-button>
|
||||
<n-button secondary type="error" size="tiny" @click="delStockGroup(result['股票代码'],result['股票名称'],group.ID)">移出分组</n-button>
|
||||
<n-button secondary type="error" size="tiny"
|
||||
@click="delStockGroup(result['股票代码'],result['股票名称'],group.ID)">移出分组
|
||||
</n-button>
|
||||
</template>
|
||||
<template #footer>
|
||||
<n-flex justify="center">
|
||||
<n-text :type="'info'">{{ result["日期"] + " " + result["时间"] }}</n-text>
|
||||
<n-tag size="small" v-if="result.volume>0" :type="result.profitType">{{ result.volume + "股" }}</n-tag>
|
||||
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">{{"成本:"+result.costPrice+"*"+result.costVolume+" "+result.profit+"%"+" ( "+result.profitAmount+" ¥ )"}}</n-tag>
|
||||
<n-tag size="small" v-if="result.costPrice>0" :type="result.profitType">
|
||||
{{ "成本:" + result.costPrice + "*" + result.costVolume + " " + result.profit + "%" + " ( " + result.profitAmount + " ¥ )" }}
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
</template>
|
||||
<template #action>
|
||||
<n-flex justify="left">
|
||||
<n-button size="tiny" type="warning" @click="setStock(result['股票代码'],result['股票名称'])"> 成本 </n-button>
|
||||
<n-button size="tiny" type="error" @click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时 </n-button>
|
||||
<n-button size="tiny" type="warning" @click="setStock(result['股票代码'],result['股票名称'])"> 成本
|
||||
</n-button>
|
||||
<n-button size="tiny" type="error"
|
||||
@click="showFenshi(result['股票代码'],result['股票名称'],result.changePercent)"> 分时
|
||||
</n-button>
|
||||
<n-button size="tiny" type="error" @click="showK(result['股票代码'],result['股票名称'])"> 日K</n-button>
|
||||
<n-button size="tiny" type="error" v-if="result['买一报价']>0" @click="showMoney(result['股票代码'],result['股票名称'])"> 资金 </n-button>
|
||||
<n-button size="tiny" type="success" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success" @click="searchNotice(result['股票代码'])"> 公告 </n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success" @click="searchStockReport(result['股票代码'])"> 研报 </n-button>
|
||||
<n-button size="tiny" type="error" v-if="result['买一报价']>0"
|
||||
@click="showMoney(result['股票代码'],result['股票名称'])"> 资金
|
||||
</n-button>
|
||||
<n-button size="tiny" type="success" @click="search(result['股票代码'],result['股票名称'])"> 详情
|
||||
</n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
||||
@click="searchNotice(result['股票代码'])"> 公告
|
||||
</n-button>
|
||||
<n-button v-if="result['买一报价']>0" size="tiny" type="success"
|
||||
@click="searchStockReport(result['股票代码'])"> 研报
|
||||
</n-button>
|
||||
<n-flex justify="right">
|
||||
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name" @select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
||||
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name"
|
||||
@select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
|
||||
<n-button type="warning" size="tiny">设置分组</n-button>
|
||||
</n-dropdown>
|
||||
</n-flex>
|
||||
@ -1900,7 +1937,8 @@ function searchStockReport(stockCode){
|
||||
</n-input-group>
|
||||
<!-- </n-card>-->
|
||||
</div>
|
||||
<n-modal transform-origin="center" size="small" v-model:show="modalShow" :title="formModel.name" style="width: 400px" :preset="'card'">
|
||||
<n-modal transform-origin="center" size="small" v-model:show="modalShow" :title="formModel.name" style="width: 400px"
|
||||
:preset="'card'">
|
||||
<n-form :model="formModel" :rules="{
|
||||
costPrice: { required: true, message: '请输入成本'},
|
||||
volume: { required: true, message: '请输入数量'},
|
||||
@ -1945,7 +1983,10 @@ function searchStockReport(stockCode){
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<template #footer>
|
||||
<n-button type="primary" @click="updateCostPriceAndVolumeNew(formModel.code,formModel.costPrice,formModel.volume,formModel.alarm,formModel)">保存</n-button>
|
||||
<n-button type="primary"
|
||||
@click="updateCostPriceAndVolumeNew(formModel.code,formModel.costPrice,formModel.volume,formModel.alarm,formModel)">
|
||||
保存
|
||||
</n-button>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
@ -1954,12 +1995,14 @@ function searchStockReport(stockCode){
|
||||
:model="addTabModel"
|
||||
size="medium"
|
||||
label-placement="left"
|
||||
> <n-grid :cols="2" >
|
||||
>
|
||||
<n-grid :cols="2">
|
||||
<n-form-item-gi label="分组名称:" path="name" :span="5">
|
||||
<n-input v-model:value="addTabModel.name" style="width: 100%" placeholder="请输入分组名称"/>
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi label="分组排序:" path="sort" :span="5">
|
||||
<n-input-number v-model:value="addTabModel.sort" style="width: 100%" min="0" placeholder="请输入分组排序值" ></n-input-number>
|
||||
<n-input-number v-model:value="addTabModel.sort" style="width: 100%" min="0"
|
||||
placeholder="请输入分组排序值"></n-input-number>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
</n-form>
|
||||
@ -1974,28 +2017,36 @@ function searchStockReport(stockCode){
|
||||
</n-flex>
|
||||
</template>
|
||||
</n-modal>
|
||||
<n-modal v-model:show="modalShow2" :title="data.name+' '+ data.changePercent+'%'" style="width: 1000px" :preset="'card'" @after-enter="handleFeishi" @after-leave="clearFeishi">
|
||||
<n-modal v-model:show="modalShow2" :title="data.name+' '+ data.changePercent+'%'" style="width: 1000px"
|
||||
:preset="'card'" @after-enter="handleFeishi" @after-leave="clearFeishi">
|
||||
<!-- <n-image :src="data.fenshiURL" />-->
|
||||
<div ref="kLineChartRef2" style="width: 1000px; height: 500px;"></div>
|
||||
</n-modal>
|
||||
<n-modal v-model:show="modalShow3" :title="data.name" style="width: 1000px" :preset="'card'" @after-enter="handleKLine">
|
||||
<n-modal v-model:show="modalShow3" :title="data.name" style="width: 1000px" :preset="'card'"
|
||||
@after-enter="handleKLine">
|
||||
<!-- <n-image :src="data.kURL" />-->
|
||||
<div ref="kLineChartRef" style="width: 1000px; height: 500px;"></div>
|
||||
</n-modal>
|
||||
|
||||
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;" :title="'['+data.name+']AI分析结果'" >
|
||||
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;"
|
||||
:title="'['+data.name+']AI分析结果'">
|
||||
<n-spin size="small" :show="data.loading">
|
||||
<MdEditor v-if="enableEditor" :toolbars="toolbars" ref="mdEditorRef" style="height: 440px;text-align: left" :modelValue="data.airesult" :theme="theme">
|
||||
<MdEditor v-if="enableEditor" :toolbars="toolbars" ref="mdEditorRef" style="height: 440px;text-align: left"
|
||||
:modelValue="data.airesult" :theme="theme">
|
||||
<template #defToolbars>
|
||||
<ExportPDF :file-name="data.name+'['+data.code+']AI分析报告'" style="text-align: left" :modelValue="data.airesult" @onProgress="handleProgress" />
|
||||
<ExportPDF :file-name="data.name+'['+data.code+']AI分析报告'" style="text-align: left"
|
||||
:modelValue="data.airesult" @onProgress="handleProgress"/>
|
||||
</template>
|
||||
</MdEditor>
|
||||
<MdPreview v-if="!enableEditor" ref="mdPreviewRef" style="height: 440px;text-align: left" :modelValue="data.airesult" :theme="theme"/>
|
||||
<MdPreview v-if="!enableEditor" ref="mdPreviewRef" style="height: 440px;text-align: left"
|
||||
:modelValue="data.airesult" :theme="theme"/>
|
||||
</n-spin>
|
||||
<template #footer>
|
||||
<n-flex justify="space-between" ref="tipsRef">
|
||||
<n-text type="info" v-if="data.time">
|
||||
<n-tag v-if="data.modelName" type="warning" round :title="data.chatId" :bordered="false">{{data.modelName}}</n-tag>
|
||||
<n-tag v-if="data.modelName" type="warning" round :title="data.chatId" :bordered="false">
|
||||
{{ data.modelName }}
|
||||
</n-tag>
|
||||
{{ data.time }}
|
||||
</n-text>
|
||||
<n-text type="error">*AI分析结果仅供参考,请以实际行情为准。投资需谨慎,风险自担。</n-text>
|
||||
@ -2004,8 +2055,10 @@ function searchStockReport(stockCode){
|
||||
<template #action>
|
||||
|
||||
<n-flex justify="space-between" style="margin-bottom: 10px">
|
||||
<n-select style="width: 49%" v-model:value="data.sysPromptId" label-field="name" value-field="ID" :options="sysPromptOptions" placeholder="请选择系统提示词" />
|
||||
<n-select style="width: 49%" v-model:value="data.question" label-field="name" value-field="content" :options="userPromptOptions" placeholder="请选择用户提示词" />
|
||||
<n-select style="width: 49%" v-model:value="data.sysPromptId" label-field="name" value-field="ID"
|
||||
:options="sysPromptOptions" placeholder="请选择系统提示词"/>
|
||||
<n-select style="width: 49%" v-model:value="data.question" label-field="name" value-field="content"
|
||||
:options="userPromptOptions" placeholder="请选择用户提示词"/>
|
||||
</n-flex>
|
||||
<n-flex justify="right">
|
||||
<n-input v-model:value="data.question" style="text-align: left" clearable
|
||||
@ -2028,7 +2081,8 @@ function searchStockReport(stockCode){
|
||||
</template>
|
||||
</n-modal>
|
||||
<n-modal v-model:show="modalShow5" :title="data.name+'资金趋势'" style="width: 1000px" :preset="'card'">
|
||||
<money-trend :code="data.code" :name="data.name" :days="360" :dark-theme="data.darkTheme" :chart-height="500"></money-trend>
|
||||
<money-trend :code="data.code" :name="data.name" :days="360" :dark-theme="data.darkTheme"
|
||||
:chart-height="500"></money-trend>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@ -2040,6 +2094,7 @@ function searchStockReport(stockCode){
|
||||
.md-editor-preview p {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* 添加闪烁效果的CSS类 */
|
||||
.blink-border {
|
||||
animation: blink-border 1s linear infinite;
|
||||
|
Loading…
x
Reference in New Issue
Block a user