專案

一般

配置概況

工作單 #199 » P9803003-Suspicious IP Drilldown.json

marlboro chu, 2025-06-30 02:03

 
{
"result" : {
"id" : 624,
"orgId" : 1,
"folderId" : 136,
"folderUid" : "bemeqa2prz7k0d",
"uid" : "denbqtfkz8um8e",
"name" : "P9803003-Suspicious IP Drilldown",
"kind" : 1,
"type" : "marcusolsson-dynamictext-panel",
"description" : "",
"model" : {
"datasource" : {
"type" : "yesoreyeram-infinity-datasource",
"uid" : "aegaeyjq187b4e"
},
"description" : "",
"fieldConfig" : {
"defaults" : {
"decimals" : 0,
"thresholds" : {
"mode" : "absolute",
"steps" : [ {
"color" : "green",
"value" : null
}, {
"color" : "red",
"value" : 80
} ]
},
"unit" : "locale"
},
"overrides" : [ ]
},
"gridPos" : {
"h" : 9,
"w" : 24,
"x" : 0,
"y" : 61
},
"id" : 9803003,
"options" : {
"afterRender" : "let p9803003_field = 'txCount';\r\nlet p9803003_sourtorder = 'desc';\r\n\r\nconst p9803003_headers = [\r\n { text: 'Source IP', field: 'Key', type: 'text' },\r\n { text: 'Countries/Regions', field: 'countryName', type: 'text' },\r\n { text: 'Volume', field: 'DocCount', type: 'number' },\r\n { text: 'Distinct Payment Cards Use', field: 'AccountCount', type: 'number' },\r\n { text: 'Number of Distinct Devices', field: 'DeviceCount', type: 'number' },\r\n { text: 'High-Risk', field: 'HighRisk', type: 'number' },\r\n];\r\n\r\n// 加總欄位\r\nconst p9803003_totals = {\r\n DocCount: 0,\r\n AccountCount: 0,\r\n DeviceCount: 0,\r\n HighRisk: 0\r\n};\r\n\r\n\r\n\r\nfunction setupP9803003TableHeader(data) {\r\n\r\n const tableHeader = document.getElementById('p9803003-table-header');\r\n tableHeader.innerHTML = '';\r\n\r\n const headerRow = document.createElement('tr');\r\n\r\n p9803003_headers.forEach(header => {\r\n const th = document.createElement('th');\r\n th.textContent = header.text;\r\n th.dataset.field = header.field;\r\n\r\n if (header.field !== 'countryName') {\r\n th.addEventListener('click', () => {\r\n if (p9803003_field === header.field) {\r\n p9803003_sourtorder = p9803003_sourtorder === 'asc' ? 'desc' : 'asc';\r\n } else {\r\n p9803003_field = header.field;\r\n p9803003_sourtorder = 'asc';\r\n }\r\n generateP9803003Items(data, p9803003_field, p9803003_sourtorder);\r\n updateP980001TableHeaderSortIndicator(headers);\r\n });\r\n }\r\n\r\n headerRow.appendChild(th);\r\n });\r\n\r\n tableHeader.appendChild(headerRow);\r\n}\r\n\r\nfunction generateP9803003Items(data, sortField = '', sortOrder = 'desc') {\r\n\r\n const tableBody = document.getElementById('p9803003-table-body');\r\n const tableFooter = document.getElementById('p9803003-table-footer');\r\n tableBody.innerHTML = '';\r\n tableFooter.innerHTML = '';\r\n\r\n // 排序\r\n data.sort((a, b) => {\r\n const valA = a[sortField];\r\n const valB = b[sortField];\r\n\r\n const numA = Number(String(valA).replace(/,/g, ''));\r\n const numB = Number(String(valB).replace(/,/g, ''));\r\n\r\n if (!isNaN(numA) && !isNaN(numB)) {\r\n return sortOrder === 'asc' ? numA - numB : numB - numA;\r\n } else {\r\n return sortOrder === 'asc'\r\n ? String(valA).localeCompare(String(valB))\r\n : String(valB).localeCompare(String(valA));\r\n }\r\n });\r\n\r\n resetP9803003Totals();\r\n\r\n data.forEach(item => {\r\n const row = document.createElement('tr');\r\n // {\r\n // const displayCountry = item.ipAddress;\r\n // row.appendChild(createP9803003Cell(displayCountry));\r\n // }\r\n // {\r\n // const displayCountry = item.countryName;\r\n // row.appendChild(createP9803003Cell(displayCountry));\r\n // }\r\n\r\n // const count = Number(String(item.txCount).replace(/,/g, '')) || 0;\r\n // const amount = Number(String(item.accountCount).replace(/,/g, '')) || 0;\r\n // const auth = Number(String(item.txCountUniDevice).replace(/,/g, '')) || 0;\r\n // const devices = Number(String(item.highCount).replace(/,/g, '')) || 0;\r\n\r\n // p9803003_totals.txCount += count;\r\n // p9803003_totals.accountCount += amount;\r\n // p9803003_totals.txCountUniDevice += auth;\r\n // p9803003_totals.highCount += devices;\r\n\r\n p9803003_headers.forEach(header => {\r\n\r\n let value = item[header.field];\r\n\r\n if (header.field === 'countryName') {\r\n value = value;\r\n } else if (header.type === 'number') {\r\n const numericValue = Number(String(value).replace(/,/g, '')) || 0;\r\n value = numericValue.toLocaleString();\r\n\r\n if (p9803003_totals.hasOwnProperty(header.field)) {\r\n p9803003_totals[header.field] += numericValue;\r\n }\r\n }\r\n row.appendChild(createP9803003Cell(value));\r\n });\r\n\r\n // row.appendChild(createP9803003Cell(count.toLocaleString()));\r\n // row.appendChild(createP9803003Cell(amount.toLocaleString()));\r\n // row.appendChild(createP9803003Cell(auth.toLocaleString()));\r\n // row.appendChild(createP9803003Cell(devices.toLocaleString()));\r\n\r\n tableBody.appendChild(row);\r\n });\r\n\r\n // 表尾加總列\r\n const footerRow = document.createElement('tr');\r\n footerRow.appendChild(createP9803003Cell('Total', true));\r\n footerRow.appendChild(createP9803003Cell('', true));\r\n footerRow.appendChild(createP9803003Cell(p9803003_totals.DocCount.toLocaleString(), true));\r\n footerRow.appendChild(createP9803003Cell(p9803003_totals.AccountCount.toLocaleString(), true));\r\n footerRow.appendChild(createP9803003Cell(p9803003_totals.DeviceCount.toLocaleString(), true));\r\n footerRow.appendChild(createP9803003Cell(p9803003_totals.HighRisk.toLocaleString(), true));\r\n tableFooter.appendChild(footerRow);\r\n}\r\n\r\nfunction createP9803003Cell(text, isFooter = false) {\r\n const cell = document.createElement('td');\r\n cell.textContent = text;\r\n if (isFooter) cell.style.fontWeight = 'bold';\r\n return cell;\r\n}\r\n\r\nfunction updateP980001TableHeaderSortIndicator(headers) {\r\n const ths = document.querySelectorAll('#p9803003-table-header th');\r\n ths.forEach(th => {\r\n const field = th.dataset.field;\r\n const header = headers.find(h => h.field === field);\r\n if (!header) return;\r\n\r\n if (field === p9803003_field) {\r\n th.textContent = `${header.text} ${p9803003_sourtorder === 'asc' ? '▲' : '▼'}`;\r\n } else {\r\n th.textContent = header.text;\r\n }\r\n });\r\n}\r\n\r\nfunction resetP9803003Totals() {\r\n for (const key in p9803003_totals) {\r\n if (Object.hasOwn(p9803003_totals, key)) p9803003_totals[key] = 0;\r\n }\r\n}\r\n\r\n// 初始化\r\nif (Array.isArray(context.data) && context.data.length > 0 && Array.isArray(context.data[0])) {\r\n const tableData = context.data[0];\r\n setupP9803003TableHeader(tableData);\r\n generateP9803003Items(tableData);\r\n}\r\n\r\n",
"content" : "<div class=\"p9803003-table-container\">\n <table class=\"p9803003-table\">\n <thead id=\"p9803003-table-header\"></thead> \n <tbody id=\"p9803003-table-body\"></tbody>\n </table>\n <p>\n <table class=\"p9803003-table-footer p9803003-table\">\n <tfoot id=\"p9803003-table-footer\"></tfoot>\n </table>\n</div>",
"contentPartials" : [ ],
"defaultContent" : "The query didn't return any results.",
"editor" : {
"format" : "auto",
"language" : "markdown"
},
"editors" : [ "afterRender", "styles" ],
"externalStyles" : [ ],
"helpers" : "",
"renderMode" : "data",
"styles" : "<style>\r\n.p9803003-table-container {\r\n width: 98%;\r\n margin: 0 auto;\r\n max-height: 180px; /* 必須設定 */\r\n overflow-y: auto; /* 讓內容可滾動 */\r\n position: relative; \r\n}\r\n\r\n/* 表格本體 */\r\n.p9803003-table {\r\n border-collapse: collapse;\r\n width: 100%;\r\n table-layout: fixed;\r\n}\r\n\r\n.p9803003-table-footer {\r\n position: sticky;\r\n bottom: 0;\r\n z-index: 3;\r\n pointer-events: none; /* 若不需互動 */\r\n backdrop-filter: blur(15px);\r\n}\r\n\r\n/* 固定 header 和 footer */\r\n.p9803003-table thead th, .p9803003-table tfoot td {\r\n position: sticky;\r\n z-index: 2;\r\n}\r\n\r\n/* 表頭固定在頂部 */\r\n.p9803003-table thead th {\r\n top: 0;\r\n text-align: center;\r\n}\r\n\r\n/* 表尾固定在底部 */\r\n.p9803003-table tfoot td {\r\n bottom: 0;\r\n}\r\n\r\n.p9803003-table td:first-child,\r\n.p9803003-table th:first-child {\r\n width: 20%;\r\n \r\n}\r\n.p9803003-table td:nth-child(2),\r\n.p9803003-table th:nth-child(2) {\r\n width: 18%;\r\n \r\n}\r\n.p9803003-table td:nth-child(3),\r\n.p9803003-table th:nth-child(3) {\r\n width: 9%;\r\n \r\n}\r\n.p9803003-table td:nth-child(4),\r\n.p9803003-table th:nth-child(4) {\r\n width: 26%;\r\n \r\n}\r\n.p9803003-table td:nth-child(6),\r\n.p9803003-table th:nth-child(6) {\r\n width: 10%;\r\n \r\n}\r\n/* 表格內容欄位 */\r\n.p9803003-table tbody td {\r\n padding: 8px;\r\n}\r\n\r\n.p9803003-table tbody td, .p9803003-table-footer tbody td, {\r\n text-align: right;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n\r\n.p9803003-table tbody td:first-child {\r\n text-align: left;\r\n}\r\n.p9803003-table tbody td:nth-child(2) {\r\n text-align: center;\r\n}\r\n.p9803003-table-footer td:nth-child(1) {\r\n text-align: left;\r\n}\r\n.p9803003-table-footer, .p9803003-table-footer td {\r\n border: none;\r\n}\r\n.p9803003-table-footer {\r\n border-top: 1px solid rgba(204, 204, 220, 0.2);;\r\n}\r\n/* 滑鼠提示效果 */\r\n.p9803003-table thead th {\r\n cursor: pointer;\r\n}\r\n.p9803003-table td {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n</style>",
"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/top5-ip-aggs",
"url_options" : {
"data" : "",
"method" : "GET",
"params" : [ {
"key" : "operator_id",
"value" : "${operator_id}"
}, {
"key" : "institute_id",
"value" : "${institute_id}"
}, {
"key" : "from_time",
"value" : "${__from}"
}, {
"key" : "to_time",
"value" : "${__to}"
}, {
"key" : "auth_token",
"value" : "${auth_token}"
}, {
"key" : "merchant_id",
"value" : "${merchant_id}"
} ]
}
} ],
"title" : "C-03. Suspicious IP Drilldown",
"transformations" : [ {
"disabled" : true,
"id" : "organize",
"options" : {
"excludeByName" : {
"authResultN" : true,
"txAmount" : true,
"txCountUniDevice" : true
},
"includeByName" : { },
"indexByName" : {
"authResultN" : 6,
"authResultY" : 4,
"countryName" : 0,
"txAmount" : 3,
"txCount" : 1,
"txCountDevice" : 5,
"txCountUniDevice" : 7,
"txRealAmount" : 2
},
"renameByName" : {
"authResultY" : "授權成功數量",
"countryName" : "國家",
"txAmount" : "交易金額(美金)",
"txCount" : "交易數量",
"txCountDevice" : "設備數量",
"txRealAmount" : "交易金額(台幣)"
}
}
} ],
"type" : "marcusolsson-dynamictext-panel"
},
"version" : 25,
"meta" : {
"folderName" : "R98-Library",
"folderUid" : "bemeqa2prz7k0d",
"connectedDashboards" : 3,
"created" : "2025-05-29T15:19:35+08:00",
"updated" : "2025-06-12T13:22:38+08:00",
"createdBy" : {
"avatarUrl" : "/avatar/ce6412d58e966caaa26cac12eb99734b",
"id" : 1,
"name" : "admin"
},
"updatedBy" : {
"avatarUrl" : "/avatar/ce6412d58e966caaa26cac12eb99734b",
"id" : 1,
"name" : "admin"
}
}
}
}
(26-26/30)