diff --git a/src/views/components/emoEnergyConverter.vue b/src/views/components/emoEnergyConverter.vue index cf98511..66e14f0 100644 --- a/src/views/components/emoEnergyConverter.vue +++ b/src/views/components/emoEnergyConverter.vue @@ -12,7 +12,7 @@ let qxnlzhqEchartsRef = ref(null); let qxnlzhqEchartsInstance = null; let regions = reactive([]); - +const dataMax=ref(null) // 设置区域名称 位置 function getNameTop(min, max, regionMiidle) { // 获取整个图表的高度 @@ -30,14 +30,30 @@ function getNumberTop(min, max, regionMax) { // 生成图形标注(核心逻辑) const generateGraphics = (min, max) => { + let hasPartialVisible = false; // 标记是否已经遇到第一个部分可见的区域 return regions.flatMap((region) => { + if(!region.min || !region.max) return []; const middleY = (Number(region.min) + Number(region.max)) / 2; - return [ - // 区域名称(中间位置) - { + const safeY = Math.max(min, Math.min(middleY, max*0.99)); + // 检查区域是否完全可见 + const isFullyVisible = region.min >= min && region.max <= max; + // 检查区域是否部分可见 + const isPartiallyVisible = (region.min < max && region.max > min) && !isFullyVisible; + // 如果已经有一个部分可见的区域名称显示了,就不再显示其他部分可见的区域名称 + if (isPartiallyVisible && hasPartialVisible) { + return []; + } + // 如果是第一个部分可见的区域,设置标记 + if (isPartiallyVisible) { + hasPartialVisible = true; + } + const graphics = []; + // 区域名称(中间位置) + if (isFullyVisible || isPartiallyVisible) { + graphics.push({ type: "text", - left: '60', // 向右调整位置 - top: getNameTop(min, max, middleY), + left: '10%', + top: getNameTop(min, max, safeY), style: { text: region.name, fill: region.fontColor, @@ -45,11 +61,13 @@ const generateGraphics = (min, max) => { fontWeight: "bold", }, z: 3, - }, - // y轴数值(顶部位置) - { + }); + } + // y轴数值(顶部位置) + if (isFullyVisible) { + graphics.push({ type: "text", - left: '60', // 向右调整位置 + left: '5%', // 向右调整位置 top: getNumberTop(min, max, region.max), // top: 100, style: { @@ -58,8 +76,9 @@ const generateGraphics = (min, max) => { fontSize: 12, }, z: 3, - }, - ]; + }); + } + return graphics; }); }; @@ -89,41 +108,41 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { min: qxnlzhqData.dd, max: qxnlzhqData.zc, name: "【情绪冰点区】", - color: "#e7a5d6", - fontColor: 'white', - NumberColor: 'blue', + color: "#FF9F9F", + fontColor: '#666666', + NumberColor: 'white', }, { min: qxnlzhqData.zc, max: qxnlzhqData.ht, name: "【认知潜伏区】", - color: "#f36587", - fontColor: 'white', - NumberColor: 'blue', + color: "#FFCB75", + fontColor: '#666666', + NumberColor: 'white', }, { min: qxnlzhqData.ht, max: qxnlzhqData.qs, name: "【多空消化区】", - color: "#e99883", - fontColor: 'white', - NumberColor: 'blue', + color: "#D7E95D", + fontColor: '#666666', + NumberColor: 'white', }, { min: qxnlzhqData.qs, max: qxnlzhqData.tp, name: "【共识加速区】", - color: "#f0db84", - fontColor: 'white', - NumberColor: 'red', + color: "#A0F56F", + fontColor: '#666666', + NumberColor: 'white', }, { min: qxnlzhqData.tp, max: qxnlzhqData.js, name: "【情绪临界区】", - color: "#dbeee3", - fontColor: 'red', - NumberColor: 'red', + color: "#87F3CD", + fontColor: '#666666', + NumberColor: 'white', }, ]; // gg yl为-1 不绘制部分图表 @@ -133,9 +152,9 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { min: qxnlzhqData.js, max: qxnlzhqData.yl, name: "【杠杆失衡区】", - color: "#9ac2d8", - fontColor: 'red', - NumberColor: 'red', + color: "#51C3F9", + fontColor: '#666666', + NumberColor: 'white', }, ) } @@ -145,13 +164,21 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { min: qxnlzhqData.yl, max: qxnlzhqData.gg, name: "【情绪熔断区】", - color: "#bce283", - fontColor: 'red', - NumberColor: 'red', + color: "#D0A7FF", + fontColor: '#666666', + NumberColor: 'white', }, ) } + // 计算动态的y轴范围 + const priceValues = kline.flatMap(item => [item[1], item[2], item[3], item[4]]); + const dataMin = Math.min(...priceValues); + const dataMax = Math.max(...priceValues); + // 获取最后一根K线数据 +const lastKLine = mixData[mixData.length - 1]; +const lastHigh = lastKLine.value[2]; // 最高价 +const lastLow = lastKLine.value[3]; // 最低价 // 计算止盈止损价格 const stopProfitPrice = Number(qxnlzhqData.cc) * 1.05; // 止盈价 const stopLossPrice = Number(qxnlzhqData.cc) * 0.97; // 止损价 @@ -257,7 +284,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { borderWidth: 1 } }, - backgroundColor: 'rgba(0, 0, 0, 0.8)', + backgroundColor: '#646E71', borderColor: '#fff', borderWidth: 1, padding: 10, @@ -299,9 +326,9 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { result += `
涨跌: ${priceChange >= 0 ? '+' : ''}${priceChange.toFixed(2)} (${changePercent}%)
` result += `` } else if (param.seriesName === '止盈线' && value !== null && value !== undefined && typeof value === 'number') { - result += `
${param.seriesName}: ${value.toFixed(2)}
` + result += `
${param.seriesName}: ${value.toFixed(2)}
` } else if (param.seriesName === '止损线' && value !== null && value !== undefined && typeof value === 'number') { - result += `
${param.seriesName}: ${value.toFixed(2)}
` + result += `
${param.seriesName}: ${value.toFixed(2)}
` } }) @@ -373,17 +400,12 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { qxnlzhqData.dd < stopLossPrice * 0.98 ? Math.floor(qxnlzhqData.dd) : Math.floor(stopLossPrice * 0.98), - max: - qxnlzhqData.yl > stopProfitPrice * 1.02 - ? Math.ceil(qxnlzhqData.yl) - : Math.ceil(stopProfitPrice * 1.02), + max: Math.max(Math.ceil(dataMax * 1.02), (qxnlzhqData.yl > 0 ? qxnlzhqData.yl : Math.ceil(dataMax * 1.02)), stopProfitPrice * 1.02), }, // 自定义区域名称和区域范围值 位置 graphic: generateGraphics(qxnlzhqData.dd < stopLossPrice * 0.98 ? Math.floor(qxnlzhqData.dd) - : Math.floor(stopLossPrice * 0.98), qxnlzhqData.yl > stopProfitPrice * 1.02 - ? Math.ceil(qxnlzhqData.yl) - : Math.ceil(stopProfitPrice * 1.02)), + : Math.floor(stopLossPrice * 0.98), Math.max(Math.ceil(dataMax * 1.02), (qxnlzhqData.yl > 0 ? qxnlzhqData.yl : Math.ceil(dataMax * 1.02)), stopProfitPrice * 1.02),), series: [ { type: "candlestick", @@ -399,10 +421,12 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { itemStyle: { normal: { // 阳线样式(收盘 > 开盘) - color: '#14b143', // 开盘价 < 收盘价时为绿色 + // color: '#14b143', // 开盘价 < 收盘价时为绿色 + color: 'rgba(0,0,0,0)', color0: '#ef232a', // 开盘价 > 收盘价时为红色 borderColor: '#14b143', // 阳线边框色(绿) borderColor0: '#ef232a', // 阴线边框色(红) + borderWidth: 1.5 } }, // 实现 分区域背景色 @@ -453,7 +477,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { symbol: 'none', lineStyle: { normal: { - color: '#ff80ff', // 蓝色 + color: '#FF0000', // 蓝色 width: 2, type: 'solid' } @@ -470,15 +494,16 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { label: { normal: { show: true, - position: 'bottom', - formatter: `{text|止盈: ${stopProfitPrice}}`, + position: 'top', + formatter: `{text|止盈}`, rich: { text: { - color: '#820a06', + color: '#FF0000', fontSize: 14, fontWeight: 'bold' } - } + }, + offset: [-20, 0] } } } @@ -492,7 +517,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { symbol: 'none', lineStyle: { normal: { - color: '#080bfd', // 红色 + color: '#001EFF', width: 2, type: 'solid' } @@ -510,20 +535,101 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { normal: { show: true, position: 'bottom', - formatter: `{text|止损: ${stopLossPrice}}`, + formatter: `{text|止损}`, rich: { text: { - color: '#080bfd', + color: '#001EFF', fontSize: 14, fontWeight: 'bold' } - } + }, + offset: [-20, 0] } } } ] } }, + { + name: '最低价', + type: 'line', + symbol: 'none', + lineStyle: { + normal: { + color: 'transparent', + width: 0 + } + }, + markPoint: { + symbol: 'circle', + symbolSize: 1, + data: [ + { + coord: [mixData.length - 1, mixData[mixData.length - 1].value[2]], + itemStyle: { + color: 'transparent' + }, + label: { + normal: { + show: true, + position: 'top', + formatter: `{text|${mixData[mixData.length - 1].value[2].toFixed(2)}}`, + rich: { + text: { + color: '#001EFF', + fontSize: 12, + fontWeight: 'bold', + textBorderColor: '#ffffff', + textBorderWidth: 2, + } + }, + offset: [20, 10] + } + } + } + ] + } + }, + { + name: '最高价', + type: 'line', + symbol: 'none', + lineStyle: { + normal: { + color: 'transparent', + width: 0 + } + }, + markPoint: { + symbol: 'circle', + symbolSize: 1, + data: [ + { + coord: [mixData.length - 1, mixData[mixData.length - 1].value[3]], + itemStyle: { + color: 'transparent' + }, + label: { + normal: { + show: true, + position: 'bottom', + formatter: `{text|${mixData[mixData.length - 1].value[3].toFixed(2)}}`, + rich: { + text: { + color: '#FF0000', + fontSize: 12, + fontWeight: 'bold', + textBorderColor: '#ffffff', + textBorderWidth: 2, + } + }, + offset: [20, -10] + } + } + } + ] + } + } ], grid: { left: "7%",