C# TCP Socket通信中粘包分包问题的解决方案与工程实践
2026/8/23 20:03:28
问题:图表数据重叠,导致无法准确点击事件;
解决方式:发现小程序里 ECharts 的 canvas tooltip 无法对单行做点击,所以改为自定义 tooltip 浮层,交互如下:
修改文件:
index.js
triggerEvent(不再通过数字点击跳转)dataIndex并显示自定义 tooltiplineclick事件index.wxml、index.wxss
<viewclass="echartsBox"><blockwx:if="{{ chartData && chartData.length }}"><ec-canvasid="{{ chartId }}"canvas-id="{{ canvasId }}"ec="{{ ec }}"></ec-canvas><viewwx:if="{{ tooltipPanel.visible }}"class="chart-tooltip-panel"style="left:{{tooltipPanel.left}}px;top:{{tooltipPanel.top}}px;"catchtap="noop"><viewclass="tooltip-title">{{ tooltipPanel.name }}</view><viewclass="tooltip-row tooltip-row-action"catchtap="onTooltipRowTap"data-type="4"><viewclass="tooltip-label"><viewclass="tooltip-marker tooltip-marker-bar"></view><text>{{ tooltipPanel.largeLabel }}</text></view><textclass="tooltip-value">{{ tooltipPanel.largeValue }}</text></view></view></block><viewwx:elseclass="empty-tip">暂无数据</view></view>/** 自定义 tooltip 预估尺寸(px),用于边界约束 */constTOOLTIP_PANEL_WIDTH=168;constTOOLTIP_PANEL_HEIGHT=128;/** * 图表点击事件 */bindChartClick(chart){if(!chart)return;constzr=chart.getZr();zr.off('click');zr.on('click',(event)=>{if(!componentRef)return;constpointInPixel=[event.offsetX,event.offsetY];if(!chart.containPixel('grid',pointInPixel)){componentRef.hideTooltipPanel();return;}constdataIndex=componentRef.resolveDataIndex(chart,pointInPixel);if(dataIndex!=null){componentRef.showTooltipPanel(dataIndex,pointInPixel);}});},/** * 显示 panel * 监听图表区域点击,按坐标换算 */showTooltipPanel(dataIndex,pointInPixel){constdataList=this.data.dataList;constitem=dataList[dataIndex];if(!item)return;constlegendData=this.properties.chartLegend||[];this.createSelectorQuery().select('.echartsBox').boundingClientRect((rect)=>{letleft=pointInPixel[0]+10;lettop=pointInPixel[1]-TOOLTIP_PANEL_HEIGHT-10;if(rect){if(left+TOOLTIP_PANEL_WIDTH>rect.width){left=rect.width-TOOLTIP_PANEL_WIDTH-8;}if(left<8)left=8;if(top<8)top=pointInPixel[1]+12;if(top+TOOLTIP_PANEL_HEIGHT>rect.height){top=rect.height-TOOLTIP_PANEL_HEIGHT-8;}}this.setData({tooltipPanel:{visible:true,left,top,dataIndex,name:item.name,// TEST ,可根据需求遍历legendData,赋值label:legendData[0],value:item.value,},});}).exec();},/** * 隐藏 panel */hideTooltipPanel(){if(!this.data.tooltipPanel.visible)return;this.setData({'tooltipPanel.visible':false,});},/** * 点击 tool 行跳转事件 */onTooltipRowTap(e){consttype=Number(e.currentTarget.dataset.ype);const{dataIndex,visible}=this.data.tooltipPanel;if(!visible||dataIndex==null)return;constdataList=this.getSortedChartData();constitem=dataList[dataIndex];if(!item)return;this.triggerEvent('lineclick',{item,dataIndex,type,});this.hideTooltipPanel();},.echartsBox{position:relative;width:100%;flex:1;min-height:0;height:100%;padding-top:20rpx;background:#fff;overflow:hidden;box-sizing:border-box;}.chart-tooltip-panel{position:absolute;z-index:10;min-width:280rpx;max-width:420rpx;padding:16rpx 20rpx;background:rgba(255,255,255,0.98);border:1px solid #e8e8e8;border-radius:8rpx;box-shadow:0 4rpx 16rpxrgba(0,0,0,0.08);box-sizing:border-box;pointer-events:auto;}.tooltip-title{margin-bottom:8rpx;font-size:22rpx;font-weight:500;color:#1e1e1e;}.tooltip-row{display:flex;align-items:center;justify-content:space-between;gap:20rpx;padding:6rpx 0;font-size:20rpx;color:#333;line-height:1.4;}.tooltip-row-action{margin:0 -12rpx;padding:10rpx 12rpx;border-radius:6rpx;}.tooltip-row-action:active{background:#f5f7fa;}.tooltip-label{display:flex;align-items:center;flex:1;min-width:0;}.tooltip-marker{flex-shrink:0;width:16rpx;height:16rpx;margin-right:10rpx;}.tooltip-marker-bar{border-radius:2rpx;background:#96e6a1;}.tooltip-value{flex-shrink:0;color:#1e1e1e;}