專案

一般

配置概況

工作單 #198 » RT9901-關連圖_force 佈局.json

marlboro chu, 2025-06-30 01:49

 
{
"datasource": {
"type": "yesoreyeram-infinity-datasource",
"uid": "aegaeyjq187b4e"
},
"description": "",
"fieldConfig": {
"defaults": {},
"overrides": []
},
"gridPos": {
"h": 12,
"w": 12,
"x": 0,
"y": 59
},
"id": 2,
"options": {
"baidu": {
"callback": "bmapReady",
"key": ""
},
"editor": {
"format": "auto"
},
"editorMode": "visual",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
"getOption": "const series = context.panel.data.series.map((s) => {\n const sData = s.fields.find((f) => f.type === 'number').values.buffer || s.fields.find((f) => f.type === 'number').values;\n const sTime = s.fields.find((f) => f.type === 'time').values.buffer || s.fields.find((f) => f.type === 'time').values;\n \n return {\n name: s.refId,\n type: 'line',\n showSymbol: false,\n areaStyle: {\n opacity: 0.1,\n },\n lineStyle: {\n width: 1,\n },\n data: sData.map((d, i) => [sTime[i], d.toFixed(2)]),\n };\n});\n\n/**\n * Enable Data Zoom by default\n */\nsetTimeout(() => context.panel.chart.dispatchAction({\n type: 'takeGlobalCursor',\n key: 'dataZoomSelect',\n dataZoomSelectActive: true,\n}), 500);\n\n/**\n * Update Time Range on Zoom\n */\ncontext.panel.chart.on('datazoom', function (params) {\n const startValue = params.batch[0]?.startValue;\n const endValue = params.batch[0]?.endValue;\n locationService.partial({ from: startValue, to: endValue });\n});\n\nreturn {\n backgroundColor: 'transparent',\n tooltip: {\n trigger: 'axis',\n },\n legend: {\n left: '0',\n bottom: '0',\n data: context.panel.data.series.map((s) => s.refId),\n textStyle: {\n color: 'rgba(128, 128, 128, .9)',\n },\n },\n toolbox: {\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n icon: {\n zoom: 'path://',\n back: 'path://',\n },\n },\n saveAsImage: {},\n }\n },\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n grid: {\n left: '2%',\n right: '2%',\n top: '2%',\n bottom: 24,\n containLabel: true,\n },\n series,\n};",
"google": {
"callback": "gmapReady",
"key": ""
},
"map": "none",
"renderer": "canvas",
"themeEditor": {
"config": "{}",
"name": "default"
},
"visualEditor": {
"code": "const data = context.panel.data;\nlet graph = {\n nodes: [],\n links: [],\n categories: []\n};\n\nif (data.series.length > 0) {\n data.series[0].fields.forEach((s) => {\n console.log(`Processing field: ${s.name}`, JSON.parse(s.values));\n if (s.name === 'links') graph.links = JSON.parse(s.values);\n else if (s.name === 'nodes') graph.nodes = JSON.parse(s.values);\n else if (s.name === 'categories') graph.categories = JSON.parse(s.values);\n });\n}\n\ngraph.nodes.forEach(node => {\n if (node.category == 0) node.category = 1;\n else if (node.category == 1) node.category = 0;\n else if (node.category == 3) node.category = 4;\n else if (node.category == 4) node.category = 3;\n});\n\ngraph.categories.forEach(categorie => {\n if (categorie.name === 'IP 1') {\n categorie.name = '設備ID-1';\n } else if (categorie.name === 'IP 2') {\n categorie.name = '設備ID-2';\n } else if (categorie.name === 'UDID 1') {\n categorie.name = '位址-1';\n } else if (categorie.name === 'UDID 2') {\n categorie.name = '位址-2';\n } else if (categorie.name === 'Account 1') {\n categorie.name = '帳號-1';\n } else if (categorie.name === 'Account 2') {\n categorie.name = '帳號-2';\n }\n});\n\nconst categoryColors = {\n 3: \"#81D4FA\", 4: \"#AED581\", 5: \"#FFB74D\",\n 0: \"#0288D1\", 1: \"#388E3C\", 2: \"#F57C00\"\n};\n\nconst triangleHeight = 1; // 頂部與底部之間的垂直距離\nconst triangleSpacing = 480; // 左右兩個三角形之間的水平距離\nconst nodeSpacing = 36; // 節點垂直間距(由水平改成垂直)\n\nconst categoryGroups = {\n 0: { baseX: -triangleSpacing, baseY: triangleHeight }, // 左頂\n 1: { baseX: -triangleSpacing - 360, baseY: triangleHeight + 180 }, // 左底左\n 2: { baseX: -triangleSpacing + 360, baseY: triangleHeight + 180 }, // 左底右\n 3: { baseX: triangleSpacing, baseY: triangleHeight }, // 右頂\n 4: { baseX: triangleSpacing - 360, baseY: triangleHeight + 180 }, // 右底左\n 5: { baseX: triangleSpacing + 360, baseY: triangleHeight + 180 } // 右底右\n};\n\n// 初始化每類別的偏移量為 0\nconst categoryOffsets = {};\nObject.keys(categoryGroups).forEach(k => categoryOffsets[k] = 0);\n\ngraph.nodes.forEach(node => {\n const cat = node.category;\n const group = categoryGroups[cat];\n const offset = categoryOffsets[cat];\n node.symbol = \"circle\"; //circle,rect,roundRect,triangle,diamond\n node.symbolSize = [12, 12];\n node.label = { show: true, position: \"inside\" };\n\n // 改為「固定 X、Y 軸上下堆疊」\n node.x = group.baseX;\n node.y = group.baseY + offset;\n categoryOffsets[cat] += nodeSpacing;\n console.log(cat + ':' + categoryOffsets[cat]);\n // 節點顏色\n node.itemStyle = {\n color: categoryColors[cat] || \"#cccccc\"\n };\n\n //categoryOffsets[cat] = categoryOffsets[cat] + 10;\n\n});\n\nconst option = {\n tooltip: {},\n legend: [\n {\n icon: 'circle',\n data: graph.categories.map(cat => cat.name),\n textStyle: {\n rich: graph.categories.reduce((acc, cat, index) => {\n acc[cat.name] = { color: categoryColors[index] };\n return acc;\n }, {})\n }\n }\n ],\n animation: false,\n series: [\n {\n name: \"Graph\",\n type: \"graph\",\n layout: \"force\",\n zoom: 0.8,\n force: {\n repulsion: [100, 1200],\n gravity: 0.1,\n edgeLength: [100, 1200],\n friction: 0.2,\n preventOverlap: true\n },\n draggable: true,\n data: graph.nodes.map(node => ({\n ...node,\n symbol: 'circle',\n symbolSize: [12, 12],\n itemStyle: {\n color: categoryColors[node.category] || \"#cccccc\"\n },\n label: {\n show: true,\n position: \"right\",\n padding: [0, 0, 0, 5],\n formatter: params => params.name.substring(0, 16),\n },\n labelLayout: {\n hideOverlap: false\n }\n })),\n links: graph.links,\n focusNodeAdjacency: false,\n categories: graph.categories.map((cat, index) => ({\n ...cat,\n itemStyle: { color: categoryColors[index] }\n })),\n roam: true,\n lineStyle: { color: \"source\", curveness: 0.3 },\n }\n ],\n graphic: graph.nodes.length === 0 ? [\n {\n type: \"text\",\n left: \"center\",\n top: \"middle\",\n style: {\n text: \"查無資訊\",\n fill: \"#999\",\n font: \"bold 20px sans-serif\"\n }\n }\n ] : []\n};\n\nreturn option;\n\n\n\n",
"dataset": [],
"series": []
}
},
"pluginVersion": "6.6.0",
"targets": [
{
"columns": [],
"datasource": {
"type": "yesoreyeram-infinity-datasource",
"uid": "aegaeyjq187b4e"
},
"filters": [],
"format": "table",
"global_query_id": "",
"parser": "backend",
"refId": "A",
"root_selector": "",
"source": "url",
"type": "json",
"url": "/smartfds-adm-web/report/api/relation",
"url_options": {
"data": "",
"headers": [],
"method": "GET",
"params": [
{
"key": "requestIP",
"value": "${query_ip}"
},
{
"key": "from_time",
"value": "${__from}"
},
{
"key": "to_time",
"value": "${__to}"
},
{
"key": "acctNumber",
"value": "${query_acct_number}"
},
{
"key": "udid",
"value": "${query_udid}"
},
{
"key": "operator_id",
"value": "${operator_id}"
},
{
"key": "institute_id",
"value": "${institute_id}"
},
{
"key": "top10udid",
"value": "${top10Udid}"
},
{
"key": "veriid_trans_id",
"value": "${query_veriid_trans_id}"
},
{
"key": "merchant_id",
"value": "${merchant_id}"
},
{
"key": "auth_token",
"value": "${auth_token}"
}
]
}
}
],
"title": "UDID Relation",
"transformations": [
{
"id": "organize",
"options": {}
}
],
"type": "volkovlabs-echarts-panel"
}
(3-3/5)