專案

一般

配置概況

工作單 #200 » P9703002-高風險交易統計資料(Top5) - Business Text.json

marlboro chu, 2025-06-30 01:59

 
{
"result" : {
"id" : 621,
"orgId" : 1,
"folderId" : 143,
"folderUid" : "bempo37hjqtq8d",
"uid" : "cen8cc4hmtywwa",
"name" : "P9703002-高風險交易統計資料(Top5) - Business Text",
"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" : 10,
"w" : 12,
"x" : 0,
"y" : 49
},
"id" : 9703002,
"options" : {
"afterRender" : "let currentHighLevelSortField = 'txCount';\r\nlet currentHighSortOrder = 'desc';\r\n\r\nconst highLevelHeaders = [\r\n { text: '國家', field: 'countryName', type: 'text' },\r\n { text: '高風險<br>交易數量', field: 'txCount', type: 'number' },\r\n { text: '交易金額<br>(台幣)', field: 'txRealAmount', type: 'number' },\r\n { text: '授權成功數量', field: 'authResultY', type: 'number' },\r\n { text: '設備數量', field: 'txCountUniDevice', type: 'number' },\r\n];\r\n\r\n// 加總欄位\r\nconst highLevelTotals = {\r\n txCount: 0,\r\n txRealAmount: 0,\r\n authResultY: 0,\r\n txCountUniDevice: 0\r\n};\r\n\r\nconst highLevelCountryMap = {\r\n \"Afghanistan\": \"阿富汗\",\r\n \"Albania\": \"阿爾巴尼亞\",\r\n \"Algeria\": \"阿爾及利亞\",\r\n \"Andorra\": \"安道爾\",\r\n \"Angola\": \"安哥拉\",\r\n \"Antigua and Barbuda\": \"安地卡\",\r\n \"Argentina\": \"阿根廷\",\r\n \"Armenia\": \"亞美尼亞\",\r\n \"Australia\": \"澳大利亞\",\r\n \"Austria\": \"奧地利\",\r\n \"Azerbaijan\": \"亞塞拜然\",\r\n \"Bahamas\": \"巴哈馬\",\r\n \"Bahrain\": \"巴林\",\r\n \"Bangladesh\": \"孟加拉\",\r\n \"Barbados\": \"巴貝多\",\r\n \"Belarus\": \"白俄羅斯\",\r\n \"Belgium\": \"比利時\",\r\n \"Belize\": \"貝里斯\",\r\n \"Benin\": \"貝南\",\r\n \"Bhutan\": \"不丹\",\r\n \"Bermuda\": \"百慕達\",\r\n \"Bolivia\": \"玻利維亞\",\r\n \"Bosnia and Herzegovina\": \"波士尼亞\",\r\n \"Botswana\": \"波札那\",\r\n \"Brazil\": \"巴西\",\r\n \"Brunei\": \"汶萊\",\r\n \"Bulgaria\": \"保加利亞\",\r\n \"Burkina Faso\": \"布吉納法索\",\r\n \"Burundi\": \"蒲隆地\",\r\n \"Cambodia\": \"柬埔寨\",\r\n \"Cameroon\": \"喀麥隆\",\r\n \"Canada\": \"加拿大\",\r\n \"Cape Verde\": \"維德角\",\r\n \"Central African\": \"中非\",\r\n \"Chad\": \"查德\",\r\n \"Chile\": \"智利\",\r\n \"China\": \"中國\",\r\n \"Colombia\": \"哥倫比亞\",\r\n \"Comoros\": \"葛摩\",\r\n \"Congo\": \"剛果\",\r\n \"Cook Islands\": \"庫克群島\",\r\n \"Costa Rica\": \"哥斯大黎加\",\r\n \"Cote d'Ivoire\": \"象牙海岸\",\r\n \"Ivory Coast\": \"象牙海岸\",\r\n \"Croatia\": \"克羅埃西亞\",\r\n \"Cuba\": \"古巴\",\r\n \"Cyprus\": \"賽普勒斯\",\r\n \"Czechia\": \"捷克\",\r\n \"Democratic Republic of the Congo\": \"剛果\",\r\n \"Democratic Congo\": \"剛果\",\r\n \"Denmark\": \"丹麥\",\r\n \"Djibouti\": \"吉布地\",\r\n \"Dominica\": \"多米尼克\",\r\n \"Dominican Republic\": \"多明尼加\",\r\n \"DPRK\": \"北韓\",\r\n \"North Korea\": \"北韓\",\r\n \"East Timor\": \"東帝汶\",\r\n \"Timor Leste\": \"東帝汶\",\r\n \"Ecuador\": \"厄瓜多\",\r\n \"Egypt\": \"埃及\",\r\n \"El Salvador\": \"薩爾瓦多\",\r\n \"Equatorial Guinea\": \"赤道幾內亞\",\r\n \"Eritrea\": \"厄利垂亞\",\r\n \"Estonia\": \"愛沙尼亞\",\r\n \"Eswatini\": \"史瓦帝尼\",\r\n \"Ethiopia\": \"衣索比亞\",\r\n \"European Union\": \"歐盟\",\r\n \"EU\": \"歐盟\",\r\n \"Fiji\": \"斐濟\",\r\n \"Finland\": \"芬蘭\",\r\n \"France\": \"法國\",\r\n \"Gabon\": \"加彭\",\r\n \"Gambia\": \"甘比亞\",\r\n \"Georgia\": \"喬治亞\",\r\n \"Germany\": \"德國\",\r\n \"Ghana\": \"迦納\",\r\n \"Greece\": \"希臘\",\r\n \"Grenada\": \"格瑞那達\",\r\n \"Guam\": \"關島\",\r\n \"Guatemala\": \"瓜地馬拉\",\r\n \"Guinea\": \"幾內亞\",\r\n \"Guinea-Bissau\": \"幾內亞比索\",\r\n \"Guyana\": \"蓋亞那\",\r\n \"Haiti\": \"海地\",\r\n \"Holy See\": \"教廷\",\r\n \"Honduras\": \"宏都拉斯\",\r\n \"Hong Kong\": \"香港\",\r\n \"Hungary\": \"匈牙利\",\r\n \"Iceland\": \"冰島\",\r\n \"India\": \"印度\",\r\n \"Indonesia\": \"印尼\",\r\n \"Iran\": \"伊朗\",\r\n \"Iraq\": \"伊拉克\",\r\n \"Ireland\": \"愛爾蘭\",\r\n \"Isle of Man\": \"曼島\",\r\n \"Israel\": \"以色列\",\r\n \"Italy\": \"義大利\",\r\n \"Jamaica\": \"牙買加\",\r\n \"Japan\": \"日本\",\r\n \"Jersey\": \"澤西島\",\r\n \"Jordan\": \"約旦\",\r\n \"Kazakhstan\": \"哈薩克\",\r\n \"Kenya\": \"肯亞\",\r\n \"Kiribati\": \"吉里巴斯\",\r\n \"Kosovo\": \"科索沃\",\r\n \"Kuwait\": \"科威特\",\r\n \"Kyrgyzstan\": \"吉爾吉斯\",\r\n \"Laos\": \"寮國\",\r\n \"Latvia\": \"拉脫維亞\",\r\n \"Lebanon\": \"黎巴嫩\",\r\n \"Lesotho\": \"賴索托\",\r\n \"Liberia\": \"賴比瑞亞\",\r\n \"Libya\": \"利比亞\",\r\n \"Liechtenstein\": \"列支敦斯登\",\r\n \"Lithuania\": \"立陶宛\",\r\n \"Luxembourg\": \"盧森堡\",\r\n \"Macao\": \"澳門\",\r\n \"Madagascar\": \"馬達加斯加\",\r\n \"Malawi\": \"馬拉威\",\r\n \"Malaysia\": \"馬來西亞\",\r\n \"Maldives\": \"馬爾地夫\",\r\n \"Mali\": \"馬利\",\r\n \"Malta\": \"馬爾他\",\r\n \"Marshall Islands\": \"馬紹爾\",\r\n \"Mauritania\": \"茅利塔尼亞\",\r\n \"Mauritius\": \"模里西斯\",\r\n \"Mexico\": \"墨西哥\",\r\n \"Micronesia\": \"密克羅尼西亞\",\r\n \"Moldova\": \"摩爾多瓦\",\r\n \"Monaco\": \"摩納哥\",\r\n \"Mongolia\": \"蒙古\",\r\n \"Montenegro\": \"蒙特內哥羅\",\r\n \"Morocco\": \"摩洛哥\",\r\n \"Mozambique\": \"莫三比克\",\r\n \"Myanmar\": \"緬甸\",\r\n \"Namibia\": \"納米比亞\",\r\n \"Nauru\": \"諾魯\",\r\n \"Nepal\": \"尼泊爾\",\r\n \"Netherlands\": \"荷蘭\",\r\n \"New Zealand\": \"紐西蘭\",\r\n \"Nicaragua\": \"尼加拉瓜\",\r\n \"Niger\": \"尼日\",\r\n \"Nigeria\": \"奈及利亞\",\r\n \"Niue\": \"紐埃\",\r\n \"North Macedonia\": \"北馬其頓\",\r\n \"Norway\": \"挪威\",\r\n \"Oman\": \"阿曼\",\r\n \"Order of Malta\": \"馬爾他騎士團\",\r\n \"Pakistan\": \"巴基斯坦\",\r\n \"Palau\": \"帛琉\",\r\n \"Panama\": \"巴拿馬\",\r\n \"Papua New Guinea\": \"巴布亞紐幾內亞\",\r\n \"Paraguay\": \"巴拉圭\",\r\n \"Peru\": \"秘魯\",\r\n \"Philippines\": \"菲律賓\",\r\n \"Poland\": \"波蘭\",\r\n \"Portugal\": \"葡萄牙\",\r\n \"Puerto Rico\": \"波多黎各\",\r\n \"Qatar\": \"卡達\",\r\n \"Romania\": \"羅馬尼亞\",\r\n \"Russia\": \"俄羅斯\",\r\n \"Rwanda\": \"盧安達\",\r\n \"Samoa\": \"薩摩亞\",\r\n \"San Marino\": \"聖馬利諾\",\r\n \"Sao Tome and Principe\": \"聖多美\",\r\n \"Saudi Arabia\": \"沙烏地阿拉伯\",\r\n \"Senegal\": \"塞內加爾\",\r\n \"Serbia\": \"塞爾維亞\",\r\n \"Seychelles\": \"塞席爾\",\r\n \"Sierra Leone\": \"獅子山\",\r\n \"Singapore\": \"新加坡\",\r\n \"Slovakia\": \"斯洛伐克\",\r\n \"Slovenia\": \"斯洛維尼亞\",\r\n \"Solomon Islands\": \"索羅門\",\r\n \"Somalia\": \"索馬利亞\",\r\n \"South Africa\": \"南非\",\r\n \"South Korea\": \"南韓\",\r\n \"South Sudan\": \"南蘇丹\",\r\n \"Spain\": \"西班牙\",\r\n \"Sri Lanka\": \"斯里蘭卡\",\r\n \"St. Kitts and Nevis\": \"聖克里斯多福\",\r\n \"St. Lucia\": \"聖露西亞\",\r\n \"St. Vincent & the Grenadines\": \"聖文森國\",\r\n \"Sudan\": \"蘇丹\",\r\n \"Suriname\": \"蘇利南\",\r\n \"Sweden\": \"瑞典\",\r\n \"Switzerland\": \"瑞士\",\r\n \"Syria\": \"敘利亞\",\r\n \"Taiwan\": \"台灣\",\r\n \"Tajikistan\": \"塔吉克\",\r\n \"Tanzania\": \"坦尚尼亞\",\r\n \"Thailand\": \"泰國\",\r\n \"Togo\": \"多哥\",\r\n \"Tonga\": \"東加\",\r\n \"Trinidad and Tobago\": \"千里達\",\r\n \"Tunisia\": \"突尼西亞\",\r\n \"Turkey\": \"土耳其\",\r\n \"Turkmenistan\": \"土庫曼\",\r\n \"Tuvalu\": \"吐瓦魯\",\r\n \"U.S.A.\": \"美國\",\r\n \"United States\": \"美國\",\r\n \"U.S. Virgin Islands\": \"英屬維京群島\",\r\n \"UAE\": \"阿聯\",\r\n \"United Arab Emirates\": \"阿聯\",\r\n \"Uganda\": \"烏干達\",\r\n \"Ukraine\": \"烏克蘭\",\r\n \"United Kingdom\": \"英國\",\r\n \"UK\": \"英國\",\r\n \"Uruguay\": \"烏拉圭\",\r\n \"Uzbekistan\": \"烏茲別克\",\r\n \"Vanuatu\": \"萬那杜\",\r\n \"Venezuela\": \"委內瑞拉\",\r\n \"Vietnam\": \"越南\",\r\n \"Yemen\": \"葉門\",\r\n \"Zambia\": \"尚比亞\",\r\n \"Zimbabwe\": \"辛巴威\",\r\n \"Other\": \"其它\"\r\n};\r\n\r\nfunction setupHighLevelTableHeader(data) {\r\n const tableHeader = document.getElementById('highlevel-table-header');\r\n tableHeader.innerHTML = '';\r\n\r\n const headerRow = document.createElement('tr');\r\n\r\n highLevelHeaders.forEach(header => {\r\n const th = document.createElement('th');\r\n th.innerHTML = 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 (currentHighLevelSortField === header.field) {\r\n currentHighSortOrder = currentHighSortOrder === 'asc' ? 'desc' : 'asc';\r\n } else {\r\n currentHighLevelSortField = header.field;\r\n currentHighSortOrder = 'asc';\r\n }\r\n generateHighLevelItems(data, currentHighLevelSortField, currentHighSortOrder);\r\n updateTableHeaderSortIndicator(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 generateHighLevelItems(data, sortField = '', sortOrder = 'desc') {\r\n const tableBody = document.getElementById('highlevel-table-body');\r\n const tableFooter = document.getElementById('highlevel-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 resetHighLevelTotals();\r\n\r\n data.forEach(item => {\r\n const row = document.createElement('tr');\r\n\r\n // const displayCountry = highLevelCountryMap[item.countryName] || item.countryName;\r\n // row.appendChild(createCell(displayCountry));\r\n\r\n // const count = Number(String(item.txCount).replace(/,/g, '')) || 0;\r\n // const amount = Number(String(item.txRealAmount).replace(/,/g, '')) || 0;\r\n // const auth = Number(String(item.authResultY).replace(/,/g, '')) || 0;\r\n // const devices = Number(String(item.txCountDevice).replace(/,/g, '')) || 0;\r\n\r\n // highLevelTotals.txCount += count;\r\n // highLevelTotals.txRealAmount += amount;\r\n // highLevelTotals.authResultY += auth;\r\n // highLevelTotals.txCountDevice += devices;\r\n\r\n // row.appendChild(createCell(count.toLocaleString()));\r\n // row.appendChild(createCell(amount.toLocaleString()));\r\n // row.appendChild(createCell(auth.toLocaleString()));\r\n // row.appendChild(createCell(devices.toLocaleString()));\r\n\r\n highLevelHeaders.forEach(header => {\r\n\r\n let value = item[header.field];\r\n\r\n if (header.field === 'countryName') {\r\n value = highLevelCountryMap[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 (highLevelTotals.hasOwnProperty(header.field)) {\r\n highLevelTotals[header.field] += numericValue;\r\n }\r\n }\r\n row.appendChild(createCell(value));\r\n });\r\n\r\n\r\n tableBody.appendChild(row);\r\n });\r\n\r\n // 表尾加總列\r\n const footerRow = document.createElement('tr');\r\n footerRow.appendChild(createCell('總計', true));\r\n footerRow.appendChild(createCell(highLevelTotals.txCount.toLocaleString(), true));\r\n footerRow.appendChild(createCell(highLevelTotals.txRealAmount.toLocaleString(), true));\r\n footerRow.appendChild(createCell(highLevelTotals.authResultY.toLocaleString(), true));\r\n footerRow.appendChild(createCell(highLevelTotals.txCountUniDevice.toLocaleString(), true));\r\n tableFooter.appendChild(footerRow);\r\n}\r\n\r\nfunction createCell(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 updateTableHeaderSortIndicator(headers) {\r\n const ths = document.querySelectorAll('#highlevel-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 === currentHighLevelSortField) {\r\n th.textContent = `${header.text} ${currentHighSortOrder === 'asc' ? '▲' : '▼'}`;\r\n } else {\r\n th.textContent = header.text;\r\n }\r\n });\r\n}\r\n\r\nfunction resetHighLevelTotals() {\r\n for (const key in highLevelTotals) {\r\n if (Object.hasOwn(highLevelTotals, key)) highLevelTotals[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 setupHighLevelTableHeader(tableData);\r\n generateHighLevelItems(tableData);\r\n}\r\n\r\n",
"content" : "<div class=\"highlevel-table-container\">\n <table class=\"highlevel-table\">\n <thead id=\"highlevel-table-header\"></thead> \n <tbody id=\"highlevel-table-body\"></tbody>\n </table>\n <p>\n <table class=\"highlevel-table-footer highlevel-table\">\n <tfoot id=\"highlevel-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\nhighlevel-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.highlevel-table {\r\n border-collapse: collapse;\r\n width: 100%;\r\n table-layout: fixed;\r\n}\r\n\r\n.highlevel-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.highlevel-table thead th, .highlevel-table tfoot td {\r\n position: sticky;\r\n z-index: 2;\r\n}\r\n\r\n/* 表頭固定在頂部 */\r\n.highlevel-table thead th {\r\n top: 0;\r\n text-align: center;\r\n}\r\n\r\n/* 表尾固定在底部 */\r\n.highlevel-table tfoot td {\r\n bottom: 0;\r\n}\r\n\r\n.highlevel-table td:first-child,\r\n.highlevel-table th:first-child {\r\n width: 20%;\r\n}\r\n\r\n/* 表格內容欄位 */\r\n.highlevel-table tbody td {\r\n padding: 8px;\r\n}\r\n\r\n/* 筆數與百分比靠右 */\r\n.highlevel-table tbody td, .highlevel-table-footer tbody td, {\r\n text-align: right;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n\r\n.highlevel-table tbody td:first-child,\r\n.highlevel-table tfoot td:first-child {\r\n text-align: center;\r\n}\r\n\r\n.highlevel-table-footer, .highlevel-table-footer td {\r\n border: none;\r\n}\r\n.highlevel-table-footer {\r\n border-top: 1px solid rgba(204, 204, 220, 0.2);;\r\n}\r\n/* 滑鼠提示效果 */\r\n.highlevel-table thead th {\r\n cursor: pointer;\r\n}\r\n.highlevel-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/high-level-top5-country-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-02. 高風險交易來源IP國家(前五大)",
"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" : 12,
"meta" : {
"folderName" : "R97-Library",
"folderUid" : "bempo37hjqtq8d",
"connectedDashboards" : 2,
"created" : "2025-05-28T16:27:07+08:00",
"updated" : "2025-06-05T09:34:17+08:00",
"createdBy" : {
"avatarUrl" : "/avatar/ce6412d58e966caaa26cac12eb99734b",
"id" : 1,
"name" : "admin"
},
"updatedBy" : {
"avatarUrl" : "/avatar/ce6412d58e966caaa26cac12eb99734b",
"id" : 1,
"name" : "admin"
}
}
}
}
(23-23/26)