⚲
專案
一般
配置概況
登入
註冊
網站首頁
專案清單
說明
搜尋
:
Grafana報表系統
全部的專案
Grafana報表系統
概觀
活動
議題清單
新聞
下載 (11.5 KB)
工作單 #199
» P98030003-高頻 IP 明細表.json
marlboro chu, 2025-06-30 02:04
{
"result"
:
{
"id"
:
624
,
"orgId"
:
1
,
"folderId"
:
136
,
"folderUid"
:
"bemeqa2prz7k0d"
,
"uid"
:
"denbqtfkz8um8e"
,
"name"
:
"P98030003-高頻 IP 明細表"
,
"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"
:
11
,
"w"
:
13
,
"x"
:
11
,
"y"
:
45
},
"id"
:
9803003
,
"options"
:
{
"afterRender"
:
"let p9803003_field = 'txCount';
\r\n
let p9803003_sourtorder = 'desc';
\r\n\r\n
const p9803003_headers = [
\r\n
{ text: 'Source IP', field: 'ipAddress' },
\r\n
{ text: 'Countries/Regions', field: 'countryNam' },
\r\n
{ text: 'Volume', field: 'txCount' },
\r\n
{ text: 'Distinct Payment Cards Use', field: 'accountCount' },
\r\n
{ text: 'Number of Distinct Devices', field: 'txCountUniDevice' },
\r\n
{ text: 'High-Risk', field: 'highCount' },
\r\n
];
\r\n\r\n
// 加總欄位
\r\n
const p9803003_totals = {
\r\n
txCount: 0,
\r\n
accountCount: 0,
\r\n
txCountUniDevice: 0,
\r\n
highCount: 0
\r\n
};
\r\n\r\n\r\n\r\n
function 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\n
function 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
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.txCount.toLocaleString(), true));
\r\n
footerRow.appendChild(createP9803003Cell(p9803003_totals.accountCount.toLocaleString(), true));
\r\n
footerRow.appendChild(createP9803003Cell(p9803003_totals.txCountUniDevice.toLocaleString(), true));
\r\n
footerRow.appendChild(createP9803003Cell(p9803003_totals.highCount.toLocaleString(), true));
\r\n
tableFooter.appendChild(footerRow);
\r\n
}
\r\n\r\n
function 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\n
function 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\n
function 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\n
if (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: 18%;
\r\n
\r\n
}
\r\n\r\n
.p9803003-table td:nth-child(3),
\r\n
.p9803003-table th:nth-child(3) {
\r\n
width: 10%;
\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: center;
\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\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"
:
10
,
"meta"
:
{
"folderName"
:
"R98-Library"
,
"folderUid"
:
"bemeqa2prz7k0d"
,
"connectedDashboards"
:
2
,
"created"
:
"2025-05-29T15:19:35+08:00"
,
"updated"
:
"2025-06-02T09:38:59+08:00"
,
"createdBy"
:
{
"avatarUrl"
:
"/avatar/ce6412d58e966caaa26cac12eb99734b"
,
"id"
:
1
,
"name"
:
"admin"
},
"updatedBy"
:
{
"avatarUrl"
:
"/avatar/ce6412d58e966caaa26cac12eb99734b"
,
"id"
:
1
,
"name"
:
"admin"
}
}
}
}
« 上一頁
1
…
28
29
30
下一頁 »
(30-30/30)
載入中...