專案

一般

配置概況

工作單 #199 » P9802002-Daily Risk Prediction Results-Bussiness Chart.json

marlboro chu, 2025-06-30 02:03

 
{
"result" : {
"id" : 634,
"orgId" : 1,
"folderId" : 136,
"folderUid" : "bemeqa2prz7k0d",
"uid" : "eeop1xq93zcaod",
"name" : "P9802002-Daily Risk Prediction Results-Bussiness Chart",
"kind" : 1,
"type" : "volkovlabs-echarts-panel",
"description" : "",
"model" : {
"datasource" : {
"type" : "elasticsearch",
"uid" : "f45b49c9-ba56-43c8-b278-a87adffdb57c"
},
"description" : "",
"fieldConfig" : {
"defaults" : { },
"overrides" : [ ]
},
"gridPos" : {
"h" : 9,
"w" : 12,
"x" : 0,
"y" : 20
},
"id" : 9802002,
"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" : "let allTimestampsSet = new Set();\nlet seriesMap = {};\nlet yAxisMax = 10;\n\ncontext.panel.data.series.forEach(serie => {\n const name = serie.name.toLowerCase();\n const timeField = serie.fields.find(f => f.name === 'Time');\n const valueField = serie.fields.find(f => f.name !== 'Time');\n\n const times = timeField.values.toArray();\n const values = valueField.values.toArray();\n\n // 將 timestamp 存入 set\n times.forEach(ts => allTimestampsSet.add(ts));\n\n // 建立 timestamp -> value 的對照表(Map)\n let valueMap = new Map();\n for (let i = 0; i < times.length; i++) {\n valueMap.set(times[i], values[i]);\n }\n\n seriesMap[name] = valueMap;\n});\n\n// 2. 整理 x 軸時間並排序(升冪)\nlet allTimestamps = Array.from(allTimestampsSet).sort();\n\n// 3. 把 timestamp 轉為 MM/dd 格式\nlet xAxisData = allTimestamps.map(ts => {\n const d = new Date(ts);\n return `${(d.getMonth() + 1).toString().padStart(2, '0')}/${d.getDate().toString().padStart(2, '0')}`;\n});\n\n// 4. 為每個 series 組出對齊的 y 資料\nfunction getSeriesData(name) {\n const valueMap = seriesMap[name] || new Map();\n return allTimestamps.map(ts => valueMap.get(ts) ?? 0); // 若沒對到則補 0\n}\n\nlet dataLow = getSeriesData('01');\nlet dataMid = getSeriesData('02');\nlet dataHigh = getSeriesData('03');\n\nlet max = Math.max(...dataLow);\nif (max > yAxisMax) yAxisMax = Math.ceil(max * 1.1);\nmax = Math.max(...dataMid);\nif (max > yAxisMax) yAxisMax = Math.ceil(max * 1.1);\nmax = Math.max(...dataHigh);\nif (max > yAxisMax) yAxisMax = Math.ceil(max * 1.1);\n\nconst magnitude = Math.pow(10, Math.floor(Math.log10(yAxisMax)));\nyAxisMax = Math.ceil(yAxisMax / magnitude) * magnitude;\n\nconst seriesConfig = [\n\n {\n name: 'low',\n data: dataLow,\n //color: 'rgb(55, 135, 45)'\n color: 'rgb(86, 166, 75)'\n },\n {\n name: 'mid',\n data: dataMid,\n color: 'rgb(242, 204, 12)'\n },\n {\n name: 'high',\n data: dataHigh,\n color: 'rgb(196, 22, 42)'\n }\n];\n\nconst seriesData = seriesConfig.map(cfg => ({\n name: cfg.name,\n type: 'bar',\n barWidth: '98%',\n data: cfg.data,\n stack: 'line',\n itemStyle: {\n color: cfg.color\n }\n}));\n\noption = {\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'line' // 或 'line',視覺效果不同\n },\n formatter: function (params) {\n let tooltipText = params[0].axisValue + '<br/>';\n params.forEach(item => {\n tooltipText += `${item.marker} ${item.seriesName}: ${item.data}<br/>`;\n });\n return tooltipText;\n }\n },\n legend: {\n left: 'left',\n bottom: '0%',\n itemHeight: 5,\n itemWidth: 15,\n padding: [10, 20, 16, 20]\n },\n xAxis: {\n type: 'category',\n data: xAxisData\n },\n yAxis: {\n type: 'value',\n // axisLabel: {\n // formatter: value => value + '%'\n // }\n min: 0,\n max: yAxisMax\n },\n grid: {\n left: '2%',\n right: '2%',\n bottom: '15%',\n top: '10%',\n containLabel: true\n },\n series: seriesData\n};\n\nreturn option;\n",
"dataset" : [ ],
"series" : [ ]
}
},
"pluginVersion" : "6.6.0",
"targets" : [ {
"alias" : "",
"bucketAggs" : [ {
"field" : "resultInfo__decisionCode",
"id" : "2",
"settings" : {
"min_doc_count" : "0",
"missing" : "未回應",
"order" : "desc",
"orderBy" : "1",
"size" : "0"
},
"type" : "terms"
}, {
"field" : "create_datetime",
"id" : "4",
"settings" : {
"interval" : "1d",
"min_doc_count" : "0",
"timeZone" : "Asia/Taipei",
"trimEdges" : "0"
},
"type" : "date_histogram"
} ],
"datasource" : {
"type" : "elasticsearch",
"uid" : "f45b49c9-ba56-43c8-b278-a87adffdb57c"
},
"metrics" : [ {
"id" : "1",
"type" : "count"
} ],
"query" : "${decision_query:raw} AND resultInfo__decisionCode : *",
"refId" : "A",
"timeField" : "create_datetime"
} ],
"title" : "B-01. Daily Transaction Risk Volume (Count by Risk Level)",
"type" : "volkovlabs-echarts-panel"
},
"version" : 5,
"meta" : {
"folderName" : "R98-Library",
"folderUid" : "bemeqa2prz7k0d",
"connectedDashboards" : 3,
"created" : "2025-06-12T10:55:22+08:00",
"updated" : "2025-06-26T13:55:02+08:00",
"createdBy" : {
"avatarUrl" : "/avatar/ce6412d58e966caaa26cac12eb99734b",
"id" : 1,
"name" : "admin"
},
"updatedBy" : {
"avatarUrl" : "/avatar/ce6412d58e966caaa26cac12eb99734b",
"id" : 1,
"name" : "admin"
}
}
}
}
(21-21/30)