Merge branch 'MHSanaei:main' into Feat-WireGuard-inbound-DNS

This commit is contained in:
SilverPolarFox 2026-05-06 19:49:08 +03:00 committed by GitHub
commit b03693db6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 68 additions and 8 deletions

View file

@ -96,7 +96,7 @@
</table>
</template>
<div class="tr-table-box">
<div class="tr-table-lt">[[ SizeFormatter.sizeFormat(getSumStats(record, client.email)) ]]</div>
<div class="tr-table-rt">[[ SizeFormatter.sizeFormat(getSumStats(record, client.email)) ]]</div>
<div class="tr-table-bar" v-if="!client.enable">
<a-progress :stroke-color="themeSwitcher.isDarkTheme ? 'rgb(72 84 105)' : '#bcbcbc'" :show-info="false" :percent="statsProgress(record, client.email)" />
</div>

View file

@ -182,6 +182,7 @@
<a-input v-if="!enableFilter" v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus
:style="{ maxWidth: '300px' }" :size="isMobile ? 'small' : ''"></a-input>
<a-radio-group v-if="enableFilter" v-model="filterBy" @change="filterInbounds" button-style="solid"
class="mobile-filter-group"
:size="isMobile ? 'small' : ''">
<a-radio-button value>{{ i18n "none" }}</a-radio-button>
<a-radio-button value="active">{{ i18n "subscription.active"
@ -2241,6 +2242,31 @@
#content-layout>.ant-layout-content>.ant-spin-nested-loading>div>.ant-spin {
left: 50vw !important;
}
/* Keep filter choices in a single horizontal line on phones. */
.inbounds-page .mobile-filter-group {
display: flex;
flex-wrap: nowrap;
max-width: 100%;
overflow-x: auto;
overflow-y: hidden;
padding-bottom: 2px;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
}
.inbounds-page .mobile-filter-group .ant-radio-button-wrapper {
flex: 0 0 auto;
white-space: nowrap;
}
/* Prevent mobile row content from splitting across multiple lines. */
.inbounds-page .ant-table-tbody > tr > td {
white-space: nowrap;
}
.inbounds-page .ant-table-tbody > tr > td:nth-child(3) {
overflow: hidden;
text-overflow: ellipsis;
}
}
/* Protocol cell — wrap tags into a flex grid with consistent gap so

View file

@ -315,13 +315,21 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
}
// Network stats
ioStats, err := net.IOCounters(false)
ioStats, err := net.IOCounters(true)
if err != nil {
logger.Warning("get io counters failed:", err)
} else if len(ioStats) > 0 {
ioStat := ioStats[0]
status.NetTraffic.Sent = ioStat.BytesSent
status.NetTraffic.Recv = ioStat.BytesRecv
} else {
var totalSent, totalRecv uint64
for _, iface := range ioStats {
name := strings.ToLower(iface.Name)
if isVirtualInterface(name) {
continue
}
totalSent += iface.BytesSent
totalRecv += iface.BytesRecv
}
status.NetTraffic.Sent = totalSent
status.NetTraffic.Recv = totalRecv
if lastStatus != nil {
duration := now.Sub(lastStatus.T)
@ -331,8 +339,6 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
status.NetIO.Up = up
status.NetIO.Down = down
}
} else {
logger.Warning("can not find io counters")
}
// TCP/UDP connections
@ -860,6 +866,34 @@ func (s *ServerService) GetXrayLogs(
return entries
}
// isVirtualInterface returns true for loopback and virtual/tunnel interfaces
// that should be excluded from network traffic statistics.
func isVirtualInterface(name string) bool {
// Exact matches
if name == "lo" || name == "lo0" {
return true
}
// Prefix matches for virtual/tunnel interfaces
virtualPrefixes := []string{
"loopback",
"docker",
"br-",
"veth",
"virbr",
"tun",
"tap",
"wg",
"tailscale",
"zt",
}
for _, prefix := range virtualPrefixes {
if strings.HasPrefix(name, prefix) {
return true
}
}
return false
}
func logEntryContains(line string, suffixes []string) bool {
for _, sfx := range suffixes {
if strings.Contains(line, sfx+"]") {