mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
Merge branch 'MHSanaei:main' into Feat-WireGuard-inbound-DNS
This commit is contained in:
commit
b03693db6d
3 changed files with 68 additions and 8 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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+"]") {
|
||||
|
|
|
|||
Loading…
Reference in a new issue