feat(stock):优化分时图展示效果

- 重新设计分时图布局和样式,增加更多图表元素
- 添加开盘价、收盘价等关键信息显示
- 实现分时图自动刷新功能
- 优化模态框样式,调整图表尺寸
- 重构相关函数,提高代码可维护性
This commit is contained in:
ArvinLovegood 2025-05-08 18:31:20 +08:00
parent df989b706b
commit 58d93c76f6

View File

@ -119,7 +119,9 @@ const data = reactive({
loading: true,
enableDanmu: false,
darkTheme:false,
changePercent:0
})
const feishiInterval= ref(null)
const currentGroupId=ref(0)
const theme=computed(() => {
return data.darkTheme ? 'dark' : 'light'
@ -246,6 +248,7 @@ onBeforeUnmount(() => {
ws.value.close()
message.destroyAll()
notify.destroyAll()
clearInterval(feishiInterval.value)
})
EventsOn("refresh",(data)=>{
@ -587,60 +590,62 @@ function setStock(code,name){
formModel.value.cron=res[0].Cron
modalShow.value=true
}
function showFenshi(code,name){
data.code=code
data.name=name
data.fenshiURL='http://image.sinajs.cn/newchart/min/n/'+data.code+'.gif'+"?t="+Date.now()
if(code.startsWith('hk')){
data.fenshiURL='http://image.sinajs.cn/newchart/hk_stock/min/'+data.code.replace("hk","")+'.gif'+"?t="+Date.now()
}
if(code.startsWith('gb_')){
data.fenshiURL='http://image.sinajs.cn/newchart/usstock/min/'+data.code.replace("gb_","")+'.gif'+"?t="+Date.now()
}
modalShow2.value=true
GetStockMinutePriceLineData(code,name).then(result => {
console.log("GetStockMinutePriceLineData",result)
const priceData=result.priceData
const chart = echarts.init(kLineChartRef2.value);
let category=[]
let price=[]
let volume=[]
let min=0
let max=0
function clearFeishi(){
console.log("clearFeishi")
clearInterval(feishiInterval.value)
}
function showFsChart(code, name) {
data.name = name
data.code = code
const chart = echarts.init(kLineChartRef2.value);
GetStockMinutePriceLineData(code, name).then(result => {
// console.log("GetStockMinutePriceLineData", result)
const priceData = result.priceData
let category = []
let price = []
let openprice=0
let closeprice=0
let volume = []
let volumeRate = []
let min = 0
let max = 0
openprice=priceData[0].price
closeprice=priceData[priceData.length-1].price
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 (min === 0 || min > priceData[i].price) {
min = priceData[i].price
}
if(max<priceData[i].price){
max=priceData[i].price
if (max < priceData[i].price) {
max = priceData[i].price
}
if(i>0){
volume.push(priceData[i].volume-priceData[i-1].volume)
}else{
if (i > 0) {
let b=priceData[i].volume - priceData[i - 1].volume
volumeRate.push(((b-volume[i-1])/volume[i-1]*100).toFixed(2))
volume.push(b)
} else {
volume.push(priceData[i].volume)
volumeRate.push(0)
}
}
let option = {
title: {
text: result.date,
subtext: "["+result.date+"] 开盘:"+openprice+" 收盘:"+closeprice+" 最高:"+max+" 最低:"+min,
left: 'center',
top: '10',
textStyle: {
color: data.darkTheme?'#ccc':'#456'
color: data.darkTheme ? '#ccc' : '#456'
}
},
legend: {
data: ['股价', '成交量'],
//orient: 'vertical',
textStyle: {
color: data.darkTheme?'#ccc':'#456'
color: data.darkTheme ? '#ccc' : '#456'
},
right: 20,
right: 50,
},
darkMode: data.darkTheme,
tooltip: {
@ -653,51 +658,191 @@ function showFenshi(code,name){
}
}
},
xAxis: {
type: 'category',
data: category
},
yAxis: [
axisPointer: {
link: [
{
name:"股价",
min: min-1,
max: max+1,
minInterval:0.01,
type: 'value'
xAxisIndex: 'all'
}
],
label: {
backgroundColor: '#888'
}
},
xAxis: [
{
type: 'category',
data: category,
axisLabel: {
show: false
}
},
{
name:"成交量",
type: 'value',
}
gridIndex: 1,
type: 'category',
data: category,
},
],
grid: [
{
left: '8%',
right: '8%',
height: '50%',
},
{
left: '8%',
right: '8%',
top: '70%',
height: '15%'
},
],
yAxis: [
{
axisLine: {
show: true
},
splitLine: {
show: false
},
name: "股价",
min: min - 1,
max: max + 1,
minInterval: 0.01,
type: 'value'
},
{
gridIndex: 1,
axisLine: {
show: true
},
splitLine: {
show: false
},
name: "成交量",
type: 'value',
},
],
visualMap: {
type: 'piecewise',
seriesIndex:0,
top: 0,
left: 10,
orient: 'horizontal',
textStyle: {
color: data.darkTheme ? '#fff' : '#456'
},
pieces: [
{
text: '低于开盘价',
gt: 0,
lte: openprice,
color: '#31F113',
textStyle: {
color: data.darkTheme ? '#fff' : '#456'
},
},
{
text: '大于开盘价小于收盘价',
gt: openprice,
lte: closeprice,
color: '#1651EF',
textStyle: {
color: data.darkTheme ? '#fff' : '#456'
},
},
{
text: '大于收盘价',
gt: closeprice,
color: '#AC3B2A',
textStyle: {
color: data.darkTheme ? '#fff' : '#456'
},
}
],
},
series: [
{
name:"股价",
name: "股价",
data: price,
type: 'line',
smooth: false,
showSymbol: false,
lineStyle: {
width: 3
},
markPoint: {
symbol: 'arrow',
symbolRotate:90,
symbolSize: [10,20],
symbolOffset: [10, 0],
itemStyle: {
color: '#FC290D'
},
label: {
position: 'right',
},
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' }
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [{ type: 'average', name: 'Avg' }]
}
symbol: 'none',
data: [
{ type: 'average', name: 'Average' },
{
lineStyle:{
color: '#FFCB00',
width: 0.5
},
yAxis: openprice,
name: '开盘价'
},
{
yAxis: closeprice ,
symbol: 'none',
lineStyle:{
color: 'red',
width: 0.5
},
}
]
},
},
{
xAxisIndex: 1,
yAxisIndex: 1,
name:"成交量",
name: "成交量",
data: volume,
type: 'bar',
}
},
]
};
chart.setOption(option);
})
}
function showFenshi(code,name,changePercent){
data.code=code
data.name=name
data.changePercent=changePercent
data.fenshiURL='http://image.sinajs.cn/newchart/min/n/'+data.code+'.gif'+"?t="+Date.now()
if(code.startsWith('hk')){
data.fenshiURL='http://image.sinajs.cn/newchart/hk_stock/min/'+data.code.replace("hk","")+'.gif'+"?t="+Date.now()
}
if(code.startsWith('gb_')){
data.fenshiURL='http://image.sinajs.cn/newchart/usstock/min/'+data.code.replace("gb_","")+'.gif'+"?t="+Date.now()
}
modalShow2.value=true
}
function handleFeishi(){
showFsChart(data.code, data.name);
feishiInterval.value=setInterval(() => {
showFsChart(data.code, data.name);
}, 1000*10)
}
function calculateMA(dayCount,values) {
@ -1526,7 +1671,7 @@ function delStockGroup(code,name,groupId){
<n-flex justify="space-between">
<n-text :type="'info'">{{result["日期"]+" "+result["时间"]}}</n-text>
<n-button size="tiny" type="info" @click="setStock(result['股票代码'],result['股票名称'])"> 成本 </n-button>
<n-button size="tiny" type="success" @click="showFenshi(result['股票代码'],result['股票名称'])"> 分时 </n-button>
<n-button size="tiny" type="success" @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="warning" @click="search(result['股票代码'],result['股票名称'])"> 详情 </n-button>
<n-dropdown trigger="click" :options="groupList" key-field="ID" label-field="name" @select="(groupId) => AddStockGroupInfo(groupId,result['股票代码'],result['股票名称'])">
@ -1635,13 +1780,13 @@ function delStockGroup(code,name,groupId){
</n-flex>
</template>
</n-modal>
<n-modal v-model:show="modalShow2" :title="data.name" style="width: 900px" :preset="'card'">
<n-modal v-model:show="modalShow2" :title="data.name" style="width: 1000px" :preset="'card'" @after-enter="handleFeishi" @after-leave="clearFeishi">
<!-- <n-image :src="data.fenshiURL" />-->
<div ref="kLineChartRef2" style="width: 850px; height: 500px;"></div>
<div ref="kLineChartRef2" style="width: 1000px; height: 500px;"></div>
</n-modal>
<n-modal v-model:show="modalShow3" :title="data.name" style="width: 900px" :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: 850px; height: 500px;"></div>
<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分析结果'" >