mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-08 14:14:19 +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>
|
</table>
|
||||||
</template>
|
</template>
|
||||||
<div class="tr-table-box">
|
<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">
|
<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)" />
|
<a-progress :stroke-color="themeSwitcher.isDarkTheme ? 'rgb(72 84 105)' : '#bcbcbc'" :show-info="false" :percent="statsProgress(record, client.email)" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,7 @@
|
||||||
<a-input v-if="!enableFilter" v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus
|
<a-input v-if="!enableFilter" v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus
|
||||||
:style="{ maxWidth: '300px' }" :size="isMobile ? 'small' : ''"></a-input>
|
:style="{ maxWidth: '300px' }" :size="isMobile ? 'small' : ''"></a-input>
|
||||||
<a-radio-group v-if="enableFilter" v-model="filterBy" @change="filterInbounds" button-style="solid"
|
<a-radio-group v-if="enableFilter" v-model="filterBy" @change="filterInbounds" button-style="solid"
|
||||||
|
class="mobile-filter-group"
|
||||||
:size="isMobile ? 'small' : ''">
|
:size="isMobile ? 'small' : ''">
|
||||||
<a-radio-button value>{{ i18n "none" }}</a-radio-button>
|
<a-radio-button value>{{ i18n "none" }}</a-radio-button>
|
||||||
<a-radio-button value="active">{{ i18n "subscription.active"
|
<a-radio-button value="active">{{ i18n "subscription.active"
|
||||||
|
|
@ -2241,6 +2242,31 @@
|
||||||
#content-layout>.ant-layout-content>.ant-spin-nested-loading>div>.ant-spin {
|
#content-layout>.ant-layout-content>.ant-spin-nested-loading>div>.ant-spin {
|
||||||
left: 50vw !important;
|
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
|
/* 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
|
// Network stats
|
||||||
ioStats, err := net.IOCounters(false)
|
ioStats, err := net.IOCounters(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("get io counters failed:", err)
|
logger.Warning("get io counters failed:", err)
|
||||||
} else if len(ioStats) > 0 {
|
} else {
|
||||||
ioStat := ioStats[0]
|
var totalSent, totalRecv uint64
|
||||||
status.NetTraffic.Sent = ioStat.BytesSent
|
for _, iface := range ioStats {
|
||||||
status.NetTraffic.Recv = ioStat.BytesRecv
|
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 {
|
if lastStatus != nil {
|
||||||
duration := now.Sub(lastStatus.T)
|
duration := now.Sub(lastStatus.T)
|
||||||
|
|
@ -331,8 +339,6 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
|
||||||
status.NetIO.Up = up
|
status.NetIO.Up = up
|
||||||
status.NetIO.Down = down
|
status.NetIO.Down = down
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logger.Warning("can not find io counters")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCP/UDP connections
|
// TCP/UDP connections
|
||||||
|
|
@ -860,6 +866,34 @@ func (s *ServerService) GetXrayLogs(
|
||||||
return entries
|
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 {
|
func logEntryContains(line string, suffixes []string) bool {
|
||||||
for _, sfx := range suffixes {
|
for _, sfx := range suffixes {
|
||||||
if strings.Contains(line, sfx+"]") {
|
if strings.Contains(line, sfx+"]") {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue