diff options
| author | Ali Golzar <57574919+aliglzr@users.noreply.github.com> | 2025-08-28 02:10:50 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-28 02:10:50 +0300 |
| commit | 3087c1b123f426b7c1306ab634fb84e7943e4217 (patch) | |
| tree | ce6f33e025bb16f73797a119a41590f03c0b8c9e /web | |
| parent | 21983971971b14377b36c8db92c8603f723f955d (diff) | |
Add all-time traffic for inbounds and clients (#3387)
* feat(db): add allTime field to Inbound and ClientTraffic models
* feat(inbound): increment all_time for inbounds and clients on traffic updates
calculate correct all_time traffic on migrate command
* feat(ui): show all-time traffic column for inbounds and its clients
* i18n: add pages.inbounds.allTimeTraffic label across locales
* Add All Time Traffic Usage in inbounds page top banner
Diffstat (limited to 'web')
| -rw-r--r-- | web/assets/js/model/dbinbound.js | 1 | ||||
| -rw-r--r-- | web/html/component/aClientTable.html | 4 | ||||
| -rw-r--r-- | web/html/inbounds.html | 34 | ||||
| -rw-r--r-- | web/service/inbound.go | 26 | ||||
| -rw-r--r-- | web/translation/translate.ar_EG.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.en_US.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.es_ES.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.fa_IR.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.id_ID.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.ja_JP.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.pt_BR.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.ru_RU.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.tr_TR.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.uk_UA.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.vi_VN.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.zh_CN.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.zh_TW.toml | 2 |
17 files changed, 84 insertions, 7 deletions
diff --git a/web/assets/js/model/dbinbound.js b/web/assets/js/model/dbinbound.js index 45301ddd..acb62ce4 100644 --- a/web/assets/js/model/dbinbound.js +++ b/web/assets/js/model/dbinbound.js @@ -6,6 +6,7 @@ class DBInbound { this.up = 0; this.down = 0; this.total = 0; + this.allTime = 0; this.remark = ""; this.enable = true; this.expiryTime = 0; diff --git a/web/html/component/aClientTable.html b/web/html/component/aClientTable.html index 359e6e74..53ec27a3 100644 --- a/web/html/component/aClientTable.html +++ b/web/html/component/aClientTable.html @@ -98,6 +98,10 @@ </table> </a-popover> </template> + +<template slot="allTime" slot-scope="text, client"> + <a-tag>[[ SizeFormatter.sizeFormat(getAllTimeClient(record, client.email)) ]]</a-tag> +</template> <template slot="expiryTime" slot-scope="text, client, index"> <template v-if="client.expiryTime !=0 && client.reset >0"> <a-popover :overlay-class-name="themeSwitcher.currentTheme"> diff --git a/web/html/inbounds.html b/web/html/inbounds.html index 010296eb..142a167c 100644 --- a/web/html/inbounds.html +++ b/web/html/inbounds.html @@ -167,28 +167,35 @@ <a-col> <a-card size="small" :style="{ padding: '16px' }" hoverable> <a-row> - <a-col :sm="12" :md="6"> + <a-col :sm="12" :md="5"> <a-custom-statistic title='{{ i18n "pages.inbounds.totalDownUp" }}' :value="`${SizeFormatter.sizeFormat(total.up)} / ${SizeFormatter.sizeFormat(total.down)}`"> <template #prefix> <a-icon type="swap"></a-icon> </template> </a-custom-statistic> </a-col> - <a-col :sm="12" :md="6"> + <a-col :sm="12" :md="5"> <a-custom-statistic title='{{ i18n "pages.inbounds.totalUsage" }}' :value="SizeFormatter.sizeFormat(total.up + total.down)" :style="{ marginTop: isMobile ? '10px' : 0 }"> <template #prefix> <a-icon type="pie-chart"></a-icon> </template> </a-custom-statistic> </a-col> - <a-col :sm="12" :md="6"> + <a-col :sm="12" :md="5"> + <a-custom-statistic title='{{ i18n "pages.inbounds.allTimeTrafficUsage" }}' :value="SizeFormatter.sizeFormat(total.allTime)" :style="{ marginTop: isMobile ? '10px' : 0 }"> + <template #prefix> + <a-icon type="history"></a-icon> + </template> + </a-custom-statistic> + </a-col> + <a-col :sm="12" :md="5"> <a-custom-statistic title='{{ i18n "pages.inbounds.inboundCount" }}' :value="dbInbounds.length" :style="{ marginTop: isMobile ? '10px' : 0 }"> <template #prefix> <a-icon type="bars"></a-icon> </template> </a-custom-statistic> </a-col> - <a-col :sm="12" :md="6"> + <a-col :sm="12" :md="4"> <a-custom-statistic title='{{ i18n "clients" }}' value=" " :style="{ marginTop: isMobile ? '10px' : 0 }"> <template #prefix> <a-space direction="horizontal"> @@ -484,6 +491,9 @@ </a-tag> </a-popover> </template> + <template slot="allTimeInbound" slot-scope="text, dbInbound"> + <a-tag>[[ SizeFormatter.sizeFormat(dbInbound.allTime || 0) ]]</a-tag> + </template> <template slot="enable" slot-scope="text, dbInbound"> <a-switch v-model="dbInbound.enable" @change="switchEnable(dbInbound.id,dbInbound.enable)"></a-switch> </template> @@ -724,6 +734,11 @@ width: 60, scopedSlots: { customRender: 'traffic' }, }, { + title: '{{ i18n "pages.inbounds.allTimeTraffic" }}', + align: 'center', + width: 60, + scopedSlots: { customRender: 'allTimeInbound' }, + }, { title: '{{ i18n "pages.inbounds.expireDate" }}', align: 'center', width: 40, @@ -759,6 +774,7 @@ { title: '{{ i18n "online" }}', width: 30, scopedSlots: { customRender: 'online' } }, { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } }, { title: '{{ i18n "pages.inbounds.traffic" }}', width: 80, align: 'center', scopedSlots: { customRender: 'traffic' } }, + { title: '{{ i18n "pages.inbounds.allTimeTraffic" }}', width: 80, align: 'center', scopedSlots: { customRender: 'allTime' } }, { title: '{{ i18n "pages.inbounds.expireDate" }}', width: 80, align: 'center', scopedSlots: { customRender: 'expiryTime' } }, { title: '{{ i18n "pages.inbounds.createdAt" }}', width: 90, align: 'center', scopedSlots: { customRender: 'createdAt' } }, { title: '{{ i18n "pages.inbounds.updatedAt" }}', width: 90, align: 'center', scopedSlots: { customRender: 'updatedAt' } }, @@ -1419,6 +1435,12 @@ clientStats = dbInbound.clientStats.find(stats => stats.email === email); return clientStats ? clientStats.up + clientStats.down : 0; }, + getAllTimeClient(dbInbound, email) { + if (email.length == 0) return 0; + clientStats = dbInbound.clientStats.find(stats => stats.email === email); + if (!clientStats) return 0; + return clientStats.allTime || (clientStats.up + clientStats.down); + }, getRemStats(dbInbound, email) { if (email.length == 0) return 0; clientStats = dbInbound.clientStats.find(stats => stats.email === email); @@ -1608,11 +1630,12 @@ }, computed: { total() { - let down = 0, up = 0; + let down = 0, up = 0, allTime = 0; let clients = 0, deactive = [], depleted = [], expiring = []; this.dbInbounds.forEach(dbInbound => { down += dbInbound.down; up += dbInbound.up; + allTime += (dbInbound.allTime || (dbInbound.up + dbInbound.down)); if (this.clientCount[dbInbound.id]) { clients += this.clientCount[dbInbound.id].clients; deactive = deactive.concat(this.clientCount[dbInbound.id].deactive); @@ -1623,6 +1646,7 @@ return { down: down, up: up, + allTime: allTime, clients: clients, deactive: deactive, depleted: depleted, diff --git a/web/service/inbound.go b/web/service/inbound.go index 4ef5fce3..78abef73 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -915,8 +915,9 @@ func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic if traffic.IsInbound { err = tx.Model(&model.Inbound{}).Where("tag = ?", traffic.Tag). Updates(map[string]any{ - "up": gorm.Expr("up + ?", traffic.Up), - "down": gorm.Expr("down + ?", traffic.Down), + "up": gorm.Expr("up + ?", traffic.Up), + "down": gorm.Expr("down + ?", traffic.Down), + "all_time": gorm.Expr("COALESCE(all_time, 0) + ?", traffic.Up+traffic.Down), }).Error if err != nil { return err @@ -962,6 +963,7 @@ func (s *InboundService) addClientTraffic(tx *gorm.DB, traffics []*xray.ClientTr if dbClientTraffics[dbTraffic_index].Email == traffics[traffic_index].Email { dbClientTraffics[dbTraffic_index].Up += traffics[traffic_index].Up dbClientTraffics[dbTraffic_index].Down += traffics[traffic_index].Down + dbClientTraffics[dbTraffic_index].AllTime += (traffics[traffic_index].Up + traffics[traffic_index].Down) // Add user in onlineUsers array on traffic if traffics[traffic_index].Up+traffics[traffic_index].Down > 0 { @@ -2035,6 +2037,26 @@ func (s *InboundService) MigrationRequirements() { tx.Rollback() } }() + + + // Calculate and backfill all_time from up+down for inbounds and clients + err = tx.Exec(` + UPDATE inbounds + SET all_time = IFNULL(up, 0) + IFNULL(down, 0) + WHERE IFNULL(all_time, 0) = 0 AND (IFNULL(up, 0) + IFNULL(down, 0)) > 0 + `).Error + if err != nil { + return + } + err = tx.Exec(` + UPDATE client_traffics + SET all_time = IFNULL(up, 0) + IFNULL(down, 0) + WHERE IFNULL(all_time, 0) = 0 AND (IFNULL(up, 0) + IFNULL(down, 0)) > 0 + `).Error + + if err != nil { + return + } // Fix inbounds based problems var inbounds []*model.Inbound diff --git a/web/translation/translate.ar_EG.toml b/web/translation/translate.ar_EG.toml index 4e4aac75..bbf68822 100644 --- a/web/translation/translate.ar_EG.toml +++ b/web/translation/translate.ar_EG.toml @@ -151,6 +151,8 @@ "getConfigError" = "حدث خطأ أثناء استرجاع ملف الإعدادات" [pages.inbounds] +"allTimeTraffic" = "إجمالي حركة المرور" +"allTimeTrafficUsage" = "إجمالي الاستخدام طوال الوقت" "title" = "الإدخالات" "totalDownUp" = "إجمالي المرسل/المستقبل" "totalUsage" = "إجمالي الاستخدام" diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 4e27908d..1531fe30 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -151,6 +151,8 @@ "getConfigError" = "An error occurred while retrieving the config file." [pages.inbounds] +"allTimeTraffic" = "All-time Traffic" +"allTimeTrafficUsage" = "All Time Total Usage" "title" = "Inbounds" "totalDownUp" = "Total Sent/Received" "totalUsage" = "Total Usage" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 3ad93de2..6a2b8958 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -151,6 +151,8 @@ "getConfigError" = "Ocurrió un error al obtener el archivo de configuración"
[pages.inbounds]
+"allTimeTraffic" = "Tráfico Total"
+"allTimeTrafficUsage" = "Uso total de todos los tiempos"
"title" = "Entradas"
"totalDownUp" = "Subidas/Descargas Totales"
"totalUsage" = "Uso Total"
diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 5e810e62..fb6d9f02 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -151,6 +151,8 @@ "getConfigError" = "خطا در دریافت فایل پیکربندی" [pages.inbounds] +"allTimeTraffic" = "کل ترافیک" +"allTimeTrafficUsage" = "کل استفاده در تمام مدت" "title" = "کاربران" "totalDownUp" = "دریافت/ارسال کل" "totalUsage" = "مصرف کل" diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml index dcfe68c0..d0d77dc3 100644 --- a/web/translation/translate.id_ID.toml +++ b/web/translation/translate.id_ID.toml @@ -151,6 +151,8 @@ "getConfigError" = "Terjadi kesalahan saat mengambil file konfigurasi" [pages.inbounds] +"allTimeTraffic" = "Total Lalu Lintas" +"allTimeTrafficUsage" = "Total Penggunaan Sepanjang Waktu" "title" = "Masuk" "totalDownUp" = "Total Terkirim/Diterima" "totalUsage" = "Penggunaan Total" diff --git a/web/translation/translate.ja_JP.toml b/web/translation/translate.ja_JP.toml index a8702cd8..3f89cf0c 100644 --- a/web/translation/translate.ja_JP.toml +++ b/web/translation/translate.ja_JP.toml @@ -151,6 +151,8 @@ "getConfigError" = "設定ファイルの取得中にエラーが発生しました" [pages.inbounds] +"allTimeTraffic" = "総トラフィック" +"allTimeTrafficUsage" = "これまでの総使用量" "title" = "インバウンド一覧" "totalDownUp" = "総アップロード / ダウンロード" "totalUsage" = "総使用量" diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml index 813a4dde..3755c61e 100644 --- a/web/translation/translate.pt_BR.toml +++ b/web/translation/translate.pt_BR.toml @@ -151,6 +151,8 @@ "getConfigError" = "Ocorreu um erro ao recuperar o arquivo de configuração" [pages.inbounds] +"allTimeTraffic" = "Tráfego Total" +"allTimeTrafficUsage" = "Uso total de todos os tempos" "title" = "Inbounds" "totalDownUp" = "Total Enviado/Recebido" "totalUsage" = "Uso Total" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index be4a1ef3..8efc4673 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -151,6 +151,8 @@ "getConfigError" = "Произошла ошибка при получении конфигурационного файла" [pages.inbounds] +"allTimeTraffic" = "Общий трафик" +"allTimeTrafficUsage" = "Общее использование за все время" "title" = "Инбаунды" "totalDownUp" = "Объем отправленного/полученного трафика" "totalUsage" = "Всего трафика" diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml index 7159c9b5..a298dd30 100644 --- a/web/translation/translate.tr_TR.toml +++ b/web/translation/translate.tr_TR.toml @@ -151,6 +151,8 @@ "getConfigError" = "Yapılandırma dosyası alınırken bir hata oluştu" [pages.inbounds] +"allTimeTraffic" = "Toplam Trafik" +"allTimeTrafficUsage" = "Tüm Zamanların Toplam Kullanımı" "title" = "Gelenler" "totalDownUp" = "Toplam Gönderilen/Alınan" "totalUsage" = "Toplam Kullanım" diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml index 95eca7a6..02ed7352 100644 --- a/web/translation/translate.uk_UA.toml +++ b/web/translation/translate.uk_UA.toml @@ -151,6 +151,8 @@ "getConfigError" = "Виникла помилка під час отримання файлу конфігурації" [pages.inbounds] +"allTimeTraffic" = "Загальний трафік" +"allTimeTrafficUsage" = "Загальне використання за весь час" "title" = "Вхідні" "totalDownUp" = "Всього надісланих/отриманих" "totalUsage" = "Всього використанно" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index f8144a2f..3f61874f 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -151,6 +151,8 @@ "getConfigError" = "Lỗi xảy ra khi truy xuất tệp cấu hình"
[pages.inbounds]
+"allTimeTraffic" = "Tổng Lưu Lượng"
+"allTimeTrafficUsage" = "Tổng mức sử dụng mọi lúc"
"title" = "Điểm vào (Inbounds)"
"totalDownUp" = "Tổng tải lên/tải xuống"
"totalUsage" = "Tổng sử dụng"
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml index 6490372c..bf19cfdb 100644 --- a/web/translation/translate.zh_CN.toml +++ b/web/translation/translate.zh_CN.toml @@ -151,6 +151,8 @@ "getConfigError" = "检索配置文件时出错" [pages.inbounds] +"allTimeTraffic" = "累计总流量" +"allTimeTrafficUsage" = "所有时间总使用量" "title" = "入站列表" "totalDownUp" = "总上传 / 下载" "totalUsage" = "总用量" diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml index cd4f22e7..dfd284d2 100644 --- a/web/translation/translate.zh_TW.toml +++ b/web/translation/translate.zh_TW.toml @@ -151,6 +151,8 @@ "getConfigError" = "檢索設定檔時發生錯誤" [pages.inbounds] +"allTimeTraffic" = "累計總流量" +"allTimeTrafficUsage" = "所有时间总使用量" "title" = "入站列表" "totalDownUp" = "總上傳 / 下載" "totalUsage" = "總用量" |
