專案

一般

配置概況

工作單 #198 » R99Lib.sql

marlboro chu, 2025-06-30 01:49

 
INSERT INTO grafana.library_element
(id, org_id, folder_id, uid, name, kind, `type`, description, model, created, created_by, updated, updated_by, version, folder_uid)
VALUES(552, 1, 131, 'eel1ofjz6mdj4f', 'RT9901- 關連圖明細', 1, 'marcusolsson-dynamictext-panel', '', '{"datasource":{"type":"yesoreyeram-infinity-datasource","uid":"aegaeyjq187b4e"},"description":"","fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[{"color":"green","value":null},{"color":"red","value":80}]}},"overrides":[{"matcher":{"id":"byName","options":"create_datetime"},"properties":[]},{"matcher":{"id":"byName","options":"level"},"properties":[]},{"matcher":{"id":"byName","options":"diiaInfo__deviceInfo__ip_request"},"properties":[]},{"matcher":{"id":"byName","options":"diiaInfo__deviceInfo__udid"},"properties":[]},{"matcher":{"id":"byName","options":"txInfo__acctNumber"},"properties":[]},{"matcher":{"id":"byName","options":"veriid_trans_id"},"properties":[]},{"matcher":{"id":"byName","options":"建立時間"},"properties":[]},{"matcher":{"id":"byName","options":"交易 IP"},"properties":[]},{"matcher":{"id":"byName","options":"設備 ID"},"properties":[]},{"matcher":{"id":"byName","options":"交易 ID"},"properties":[]}]},"gridPos":{"h":12,"w":12,"x":0,"y":2},"id":13,"options":{"afterRender":"let currentSortField = ''merchantName''; // 預設排序欄位\\r\\nlet currentSortOrder = ''asc''; // 預設排序方向\\r\\n\\r\\nfunction generateRelationItems(data, sortField = ''txCount'', sortOrder = ''desc'') {\\r\\n const tableBody = document.getElementById(''relation-table-body'');\\r\\n tableBody.innerHTML = ''''; // 清空舊資料\\r\\n\\r\\n // 排序\\r\\n data.sort((a, b) =\\u003e {\\r\\n const rawA = a[sortField];\\r\\n const rawB = b[sortField];\\r\\n\\r\\n // 嘗試把逗號移除,轉成數字\\r\\n const numA = typeof rawA === ''string'' ? Number(rawA.replace(/,/g, '''')) : rawA;\\r\\n const numB = typeof rawB === ''string'' ? Number(rawB.replace(/,/g, '''')) : rawB;\\r\\n\\r\\n if (!isNaN(numA) \\u0026\\u0026 !isNaN(numB)) {\\r\\n // 都是有效數字,就用數字比較\\r\\n return sortOrder === ''asc'' ? numA - numB : numB - numA;\\r\\n } else {\\r\\n // 有不是數字,就當字串比\\r\\n return sortOrder === ''asc''\\r\\n ? String(rawA).localeCompare(String(rawB))\\r\\n : String(rawB).localeCompare(String(rawA));\\r\\n }\\r\\n });\\r\\n\\r\\n // 產生每一列\\r\\n data.forEach(item =\\u003e {\\r\\n const row = document.createElement(''tr'');\\r\\n\\r\\n // 商店名稱\\r\\n const merchantNameCell = document.createElement(''td'');\\r\\n merchantNameCell.className = ''kpi-merchant-name'';\\r\\n merchantNameCell.textContent = item.create_datetime;\\r\\n row.appendChild(merchantNameCell);\\r\\n\\r\\n // 其他欄位\\r\\n const kpiFields = [\\r\\n item.diiaInfo__deviceInfo__udid,\\r\\n item.diiaInfo__deviceInfo__ip_request,\\r\\n item.veriid_trans_id,\\r\\n item.txInfo__acctNumber,\\r\\n ];\\r\\n\\r\\n kpiFields.forEach(value =\\u003e {\\r\\n const cell = document.createElement(''td'');\\r\\n cell.className = ''kpi-value'';\\r\\n cell.textContent = value;\\r\\n row.appendChild(cell);\\r\\n });\\r\\n\\r\\n tableBody.appendChild(row);\\r\\n });\\r\\n}\\r\\n\\r\\nfunction setupRelationTableHeader(data) {\\r\\n const tableHeader = document.getElementById(''relation-table-header'');\\r\\n tableHeader.innerHTML = ''''; // 清空舊表頭\\r\\n\\r\\n // 中文表頭設定\\r\\n const headers = [\\r\\n { text: ''Date Time'', field: ''create_datetime'' },\\r\\n { text: ''UDID'', field: ''diiaInfo__deviceInfo__udid'' },\\r\\n { text: ''IP'', field: ''diiaInfo__deviceInfo__ip_request'' },\\r\\n { text: ''Transaction ID'', field: ''veriid_trans_id'' },\\r\\n { text: ''Account Number'', field: ''txInfo__acctNumber'' },\\r\\n ];\\r\\n\\r\\n const headerRow = document.createElement(''tr'');\\r\\n\\r\\n headers.forEach(header =\\u003e {\\r\\n const th = document.createElement(''th'');\\r\\n th.textContent = header.text;\\r\\n th.style.cursor = ''pointer''; // 鼠標提示可以點\\r\\n th.addEventListener(''click'', () =\\u003e {\\r\\n if (currentSortField === header.field) {\\r\\n currentSortOrder = currentSortOrder === ''asc'' ? ''desc'' : ''asc'';\\r\\n } else {\\r\\n currentSortField = header.field;\\r\\n currentSortOrder = ''asc'';\\r\\n }\\r\\n generateRelationItems(data, currentSortField, currentSortOrder);\\r\\n updateTableHeaderSortIndicator(headers);\\r\\n });\\r\\n th.dataset.field = header.field; // 記錄欄位屬性 (方便加箭頭)\\r\\n headerRow.appendChild(th);\\r\\n });\\r\\n\\r\\n tableHeader.appendChild(headerRow);\\r\\n}\\r\\n\\r\\nfunction updateTableHeaderSortIndicator(headers) {\\r\\n const thElements = document.querySelectorAll(''#relation-table-header th'');\\r\\n thElements.forEach(th =\\u003e {\\r\\n const field = th.dataset.field;\\r\\n const header = headers.find(h =\\u003e h.field === field);\\r\\n if (!header) return;\\r\\n\\r\\n if (field === currentSortField) {\\r\\n th.textContent = ``${header.text} ${currentSortOrder === ''asc'' ? '''' : ''''}``;\\r\\n } else {\\r\\n th.textContent = header.text;\\r\\n }\\r\\n });\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n// 初始化\\r\\nif (Array.isArray(context.data) \\u0026\\u0026 context.data.length \\u003e 0) {\\r\\n const tableData = context.data[0];\\r\\n setupRelationTableHeader(tableData);\\r\\n generateRelationItems(tableData);\\r\\n}\\r\\n","content":"\\u003ctable id=\\"relation-table\\" class=\\"relation-table\\"\\u003e\\n \\u003cthead id=\\"relation-table-header\\"\\u003e\\n \\u003c!-- JS 會產生表頭 --\\u003e\\n \\u003c/thead\\u003e\\n \\u003ctbody id=\\"relation-table-body\\"\\u003e\\n \\u003c!-- Data will be populated by JavaScript --\\u003e\\n \\u003c/tbody\\u003e\\n \\u003c!-- \\u003ctfoot id=\\"relation-table-footer\\"\\u003e\\u003c/tfoot\\u003e --\\u003e\\n\\u003c/table\\u003e","contentPartials":[],"defaultContent":"The query didn''t return any results.","editor":{"format":"auto","language":"markdown"},"editors":["afterRender","styles"],"externalStyles":[],"helpers":"","renderMode":"data","styles":"\\u003cstyle\\u003e\\r\\n/* 基本字型與排版 */\\r\\n.kpi-grid {\\r\\n display: grid;\\r\\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\\r\\n gap: 24px;\\r\\n padding: 20px;\\r\\n font-family: ''Segoe UI'', ''Roboto Mono'', ''Noto Sans TC'', monospace;\\r\\n}\\r\\n\\r\\n/* KPI 項目 */\\r\\n.kpi-item {\\r\\n border: 1px solid rgba(100, 181, 246, 0.4);\\r\\n border-radius: 12px;\\r\\n padding: 16px 20px;\\r\\n background: linear-gradient(160deg, rgba(30, 30, 30, 0.9), rgba(40, 40, 40, 0.6));\\r\\n box-shadow: 0 0 12px rgba(66, 165, 245, 0.2);\\r\\n transition: transform 0.2s ease;\\r\\n color: #fff;\\r\\n}\\r\\n.kpi-item:hover {\\r\\n transform: scale(1.02);\\r\\n box-shadow: 0 0 20px rgba(66, 165, 245, 0.4);\\r\\n}\\r\\n\\r\\n/* 表格樣式 */\\r\\n.relation-table {\\r\\n margin: auto;\\r\\n border-collapse: collapse;\\r\\n table-layout: fixed;\\r\\n border: 1px solid rgba(100, 181, 246, 0.2);\\r\\n font-family: ''Segoe UI'', ''Roboto Mono'', ''Noto Sans TC'', monospace;\\r\\n // color: #fff;\\r\\n}\\r\\n\\r\\n/* Sticky 表頭和表尾 */\\r\\n.relation-table thead th,\\r\\n.relation-table tfoot td {\\r\\n position: sticky;\\r\\n z-index: 1;\\r\\n color: #fff; \\r\\n background: rgba(30, 30, 30, 0.95);\\r\\n}\\r\\n\\r\\n.relation-table thead th {\\r\\n top: 0;\\r\\n font-size: 12px;\\r\\n text-align: center;\\r\\n border-bottom: 1px solid rgba(100, 181, 246, 0.4);\\r\\n}\\r\\n\\r\\n.relation-table tfoot td {\\r\\n bottom: 0;\\r\\n font-weight: bold;\\r\\n border-top: 1px solid rgba(100, 181, 246, 0.4);\\r\\n}\\r\\n\\r\\n/* 表格內容 */\\r\\n.relation-table th,\\r\\n.relation-table td {\\r\\n padding: 8px 12px;\\r\\n min-width: 160px;\\r\\n text-align: right;\\r\\n white-space: nowrap;\\r\\n width: auto;\\r\\n}\\r\\n\\r\\n.relation-table td:last-child {\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.relation-table td.kpi-merchant-name {\\r\\n font-size: 14px;\\r\\n letter-spacing: 1px;\\r\\n text-transform: uppercase;\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.relation-table td.kpi-value {\\r\\n font-size: 14px;\\r\\n color: rgb(44, 132, 198);\\r\\n font-variant-numeric: tabular-nums;\\r\\n}\\r\\n\\r\\n.relation-table td.kpi-label {\\r\\n font-size: 14px;\\r\\n letter-spacing: 1px;\\r\\n text-transform: uppercase;\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.relation-table tbody tr:hover {\\r\\n transform: scale(1.02);\\r\\n box-shadow: 0 0 20px rgba(66, 165, 245, 0.4);\\r\\n transition: all 0.2s ease;\\r\\n}\\r\\n\\r\\n\\r\\n","wrap":true},"pluginVersion":"5.7.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-data","url_options":{"data":"","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":" ","transformations":[{"id":"organize","options":{"excludeByName":{"diiaInfo__deviceInfo__ip_src_latitude":true,"diiaInfo__deviceInfo__ip_src_longitude":true},"includeByName":{},"indexByName":{"create_datetime":0,"diiaInfo__deviceInfo__ip_request":3,"diiaInfo__deviceInfo__udid":2,"level":5,"txInfo__acctNumber":4,"veriid_trans_id":1},"renameByName":{}}},{"id":"sortBy","options":{"fields":{},"sort":[{"desc":true,"field":"create_datetime"}]}}],"type":"marcusolsson-dynamictext-panel"}', '2025-05-06 15:18:14', 1, '2025-05-15 10:52:11', 1, 12, 'RT99-Library');
INSERT INTO grafana.library_element
(id, org_id, folder_id, uid, name, kind, `type`, description, model, created, created_by, updated, updated_by, version, folder_uid)
VALUES(554, 1, 131, 'fel1ogkqetzpca', 'RT9901-關連圖_force 佈局', 1, 'volkovlabs-echarts-panel', '', '{"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) =\\u003e {\\n const sData = s.fields.find((f) =\\u003e f.type === ''number'').values.buffer || s.fields.find((f) =\\u003e f.type === ''number'').values;\\n const sTime = s.fields.find((f) =\\u003e f.type === ''time'').values.buffer || s.fields.find((f) =\\u003e 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) =\\u003e [sTime[i], d.toFixed(2)]),\\n };\\n});\\n\\n/**\\n * Enable Data Zoom by default\\n */\\nsetTimeout(() =\\u003e 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) =\\u003e 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 \\u003e 0) {\\n data.series[0].fields.forEach((s) =\\u003e {\\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 =\\u003e {\\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 =\\u003e {\\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 =\\u003e categoryOffsets[k] = 0);\\n\\ngraph.nodes.forEach(node =\\u003e {\\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 =\\u003e cat.name),\\n textStyle: {\\n rich: graph.categories.reduce((acc, cat, index) =\\u003e {\\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 =\\u003e ({\\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 =\\u003e 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) =\\u003e ({\\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"}', '2025-05-06 15:18:33', 1, '2025-06-13 16:12:22', 1, 15, 'RT99-Library');
INSERT INTO grafana.library_element
(id, org_id, folder_id, uid, name, kind, `type`, description, model, created, created_by, updated, updated_by, version, folder_uid)
VALUES(555, 1, 131, 'bel1ogy4i8i68c', 'RT9901-關連圖_none 佈局', 1, 'volkovlabs-echarts-panel', '', '{"datasource":{"type":"yesoreyeram-infinity-datasource","uid":"aegaeyjq187b4e"},"description":"","fieldConfig":{"defaults":{},"overrides":[]},"gridPos":{"h":12,"w":12,"x":12,"y":59},"id":5,"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) =\\u003e {\\n const sData = s.fields.find((f) =\\u003e f.type === ''number'').values.buffer || s.fields.find((f) =\\u003e f.type === ''number'').values;\\n const sTime = s.fields.find((f) =\\u003e f.type === ''time'').values.buffer || s.fields.find((f) =\\u003e 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) =\\u003e [sTime[i], d.toFixed(2)]),\\n };\\n});\\n\\n/**\\n * Enable Data Zoom by default\\n */\\nsetTimeout(() =\\u003e 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) =\\u003e 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 \\u003e 0) {\\n data.series[0].fields.forEach((s) =\\u003e {\\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 =\\u003e {\\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 =\\u003e {\\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\\n// 畫布寬度\\nconst canvasWidth = 640;\\nconst colSpacing = canvasWidth / 3; // 每列的間距\\n//const colSpacing = 10;\\nconst rowSpacing = 18; // 調整節點垂直間距為 15px\\n\\nconst categoryXPositions = {};\\n\\n// 讓 6 種 category 均分 X 軸\\nfor (let i = 0; i \\u003c 6; i++) {\\n categoryXPositions[i] = -canvasWidth / 2 + i * colSpacing + colSpacing / 2;\\n}\\n\\n// **讓節點從 ``top: 15px`` 開始**\\nlet categoryYPositions = { 0: 15, 1: 15, 2: 15, 3: 15, 4: 15, 5: 15 };\\n\\n\\n// 設定節點樣式 \\u0026 位置\\ngraph.nodes.forEach((node) =\\u003e {\\n node.symbol = \\"circle\\"; // 設定為圓點\\n node.symbolSize = 12; // 稍微放大圓點\\n node.label = { show: true, position: \\"inside\\" };\\n\\n // **設定 X、Y 軸座標**\\n node.x = categoryXPositions[node.category]; // 分成 6 列\\n node.y = categoryYPositions[node.category]; // 從 ``top 15px`` 開始\\n categoryYPositions[node.category] += rowSpacing; // 下個同類別的節點往下擺\\n\\n node.itemStyle = { color: categoryColors[node.category] || \\"#cccccc\\" };\\n});\\n\\nreturn {\\n tooltip: {},\\n legend: [\\n {\\n icon: ''circle'',\\n data: graph.categories.map(a =\\u003e a.name)\\n }\\n ],\\n animationDurationUpdate: 1500,\\n animationEasingUpdate: \\"quinticInOut\\",\\n series: [\\n {\\n name: \\"Graph\\",\\n type: \\"graph\\",\\n layout: \\"none\\", // 固定座標\\n data: graph.nodes.map((node) =\\u003e ({\\n ...node,\\n draggable: true, // 允許拖曳\\n itemStyle: { color: categoryColors[node.category] || \\"#cccccc\\" },\\n symbol: ''circle'',\\n symbolSize: [12, 12],\\n label: {\\n show: true,\\n position: \\"right\\",\\n padding: [0, 0, 0, 5],\\n formatter: params =\\u003e params.name.substring(0, 16),\\n },\\n })),\\n links: graph.links,\\n categories: graph.categories.map((cat, index) =\\u003e ({\\n ...cat,\\n itemStyle: { color: categoryColors[index] || \\"#cccccc\\" }\\n })),\\n roam: true, // 允許拖曳,但不會影響原始佈局\\n focusNodeAdjacency: false,\\n lineStyle: {\\n color: \\"source\\",\\n curveness: 0.3\\n }\\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","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 II","transformations":[{"id":"organize","options":{}}],"type":"volkovlabs-echarts-panel"}', '2025-05-06 15:18:40', 1, '2025-06-13 15:42:41', 1, 14, 'RT99-Library');
(1-1/5)