当前位置: 首页 > news >正文

Grafana 表格自定义下载样式。

我这边的方案是通过 grafana嵌套在iframe中,然后获取数据postmessage 给父页面 调用 excel.js 下载。

增加一个html panel , 在 onlint 添加如下代码。

该代码会在目标panel的标题上 增加一个 按钮,点击后触发。

var targetPanelId = 8; setTimeout(function() { var panel = $('.react-grid-item[data-panelid="' + targetPanelId + '"]'); var header = panel.find('[data-testid="header-container"]'); if (header.length === 0) header = panel.find('header'); var btn = $('<button>⬇ Download</button>') .attr('contenteditable', 'false') .css({ 'padding': '2px 12px', 'font-size': '12px', 'background': '#000', 'color': '#fff', 'border': 'none', 'border-radius': '4px', 'cursor': 'pointer', 'user-select': 'none', 'pointer-events': 'auto', 'z-index': '99999' }); btn.on('click', function(e) { e.stopPropagation(); e.stopImmediatePropagation(); // ★ 从 React 内部直接取当前显示的完整数据 function extractData(el) { var fiberKey = Object.keys(el).find(function(k) { return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'); }); if (!fiberKey) return null; var fiber = el[fiberKey]; var node = fiber; var depth = 100; while (node && depth-- > 0) { var p = node.memoizedProps || {}; // Grafana 把查询结果放在 props.data.series if (p.data && p.data.series && p.data.series.length > 0) { return p.data.series; } if (p.data && Array.isArray(p.data.fields)) { return [p.data]; } if (p.frames && p.frames.length > 0) { return p.frames; } node = node.return; } return null; } // 从 panel 容器开始找 var frames = null; var dom = panel[0]; // 先从 panel 根元素找 frames = extractData(dom); // 没找到就遍历子元素 if (!frames) { var children = dom.querySelectorAll('div'); for (var i = 0; i < children.length && !frames; i++) { frames = extractData(children[i]); } } if (!frames || frames.length === 0) { console.error('❌ 未找到数据'); return; } // 解析 DataFrame → headers + rows var headers = []; var rows = []; frames.forEach(function(frame) { var fields = frame.fields || []; if (fields.length === 0) return; if (headers.length === 0) { headers = fields.map(function(f) { return f.config && f.config.displayName ? f.config.displayName : f.name || ''; }); } // values 可能是数组、ArrayVector、TypedArray var columns = fields.map(function(f) { var v = f.values; if (Array.isArray(v)) return v; if (v && v.buffer) return Array.from(v.buffer); if (v && v.toArray) return v.toArray(); if (v && typeof v.length === 'number') return Array.from(v); return []; }); var rowCount = columns[0] ? columns[0].length : 0; for (var i = 0; i < rowCount; i++) { var row = []; for (var j = 0; j < columns.length; j++) { var cell = columns[j][i]; // 时间戳转可读 if (fields[j].type === 'time' && typeof cell === 'number') { cell = new Date(cell > 1e12 ? cell : cell * 1000) .toISOString().replace('T', ' ').slice(0, 19); } row.push(cell != null ? cell : ''); } rows.push(row); } }); console.log('📊 表头:', headers); console.log('📊 行数:', rows.length); console.log('📊 前3行:', rows.slice(0, 3)); // postMessage 给父页面 var message = { type: 'GRAFANA_PANEL_DATA', panelId: targetPanelId, timestamp: new Date().toISOString(), data: { headers: headers, rows: rows, rowCount: rows.length } }; if (window.parent && window.parent !== window) { window.parent.postMessage(message, '*'); } else { window.postMessage(message, '*'); } console.log('✅ 已发送 ' + rows.length + ' 行'); }); btn.on('mousedown pointerdown dragstart', function(e) { e.stopPropagation(); e.stopImmediatePropagation(); }); header.css({ 'display': 'flex', 'align-items': 'center' }); header.append(btn); }, 1000);


http://www.jsqmd.com/news/586326/

相关文章:

  • 深入解析Bootstrap Datepicker:现代Web应用中的日期选择最佳实践
  • 猫抓资源嗅探工具:5步快速下载网页视频音频的终极指南
  • 零基础入门chatgpt集成:借助快马平台轻松创建你的第一个ai对话程序
  • 如何在Windows上获得完美的B站桌面体验?BiliBili-UWP终极指南
  • Ostrakon-VL-8B部署避坑指南:图片重采样防GPU崩溃配置
  • Ostrakon-VL终端教程:多用户会话隔离与数据权限控制
  • FLAC 1.5.0:无损音频压缩的革命性突破,如何为你的音乐收藏节省50%空间?
  • Latex论文排版必备:3分钟搞定参考文献和图表引用的颜色自定义(附hyperref配置详解)
  • 华硕笔记本性能控制终极指南:如何用G-Helper替代臃肿的Armoury Crate
  • 效率提升秘籍:用快马AI一键生成智能书签与网址检索助手
  • TensorFlow-v2.9快速上手指南:从安装到运行第一个程序
  • 高效掌控3D打印的终极方案:FullControl GCode Designer完全指南
  • 终极指南:BililiveRecorder 直播录制文件修复全攻略
  • yz-bijini-cosplay部署案例:Z-Image底座免重载,4090显卡高效出图
  • seo外包后如何维护网站优化效果
  • Granite-4.0-H-350M新手入门:零基础在边缘设备部署文本生成模型
  • OpenClaw安全实践:Qwen3.5-9B本地化处理敏感财务数据
  • 虚拟手柄如何重构游戏操控体验?3个创新突破让玩家操作效率提升3倍
  • GitHub小白入门指南:用快马AI轻松理解你的第一个开源项目
  • 杰理696sdk APP配置
  • 魔兽争霸III现代兼容性终极指南:用Warcraft Helper重获完美体验
  • 新手友好:在快马平台上通过实践项目轻松理解mcp协议
  • 7大实战技巧精通DLT Viewer:汽车电子日志分析权威指南
  • 攻克跨浏览器测试难题:Playwright Python全流程实践
  • GHelper:重构华硕笔记本性能控制的轻量级开源工具
  • palera1n越狱探索:A8-A11设备的iOS 15+安全越狱指南(附双模式操作与问题排查)
  • 里太智寻全域营销作为专业的GEO推广服务商,费用贵吗 - mypinpai
  • 3步掌握猫抓扩展:网页资源嗅探工具全面使用指南
  • HackRF设备Windows驱动问题全解决方案:从诊断到优化
  • 研究生面试避坑指南:如何用3C原则打造高通过率英文回答(附真实案例)