mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-08 14:36:13 +00:00
subpage: enabled state
Track and surface a subscription's enabled state from backend to frontend so the UI can show inactive subscriptions and use it in active-state logic. Changes: - sub/subService.go: track hasEnabledClient, set traffic.Enable, add Enabled to PageData and populate it in BuildPageData. - sub/subController.go: include enabled in the page context. - web/html/settings/panel/subscription/subpage.html: emit data-enabled attribute and render an "inactive" tag when disabled. - web/assets/js/subscription.js: read data-enabled and include it in isActive() checks. This ensures subscriptions with no enabled clients are marked inactive in the UI and excluded from being considered active.
This commit is contained in:
@@ -138,6 +138,7 @@ func (a *SUBController) subs(c *gin.Context) {
|
|||||||
"host": page.Host,
|
"host": page.Host,
|
||||||
"base_path": page.BasePath,
|
"base_path": page.BasePath,
|
||||||
"sId": page.SId,
|
"sId": page.SId,
|
||||||
|
"enabled": page.Enabled,
|
||||||
"download": page.Download,
|
"download": page.Download,
|
||||||
"upload": page.Upload,
|
"upload": page.Upload,
|
||||||
"total": page.Total,
|
"total": page.Total,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.C
|
|||||||
var result []string
|
var result []string
|
||||||
var traffic xray.ClientTraffic
|
var traffic xray.ClientTraffic
|
||||||
var lastOnline int64
|
var lastOnline int64
|
||||||
|
var hasEnabledClient bool
|
||||||
var clientTraffics []xray.ClientTraffic
|
var clientTraffics []xray.ClientTraffic
|
||||||
inbounds, err := s.getInboundsBySubId(subId)
|
inbounds, err := s.getInboundsBySubId(subId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -78,6 +79,9 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.C
|
|||||||
}
|
}
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.SubID == subId {
|
if client.SubID == subId {
|
||||||
|
if client.Enable {
|
||||||
|
hasEnabledClient = true
|
||||||
|
}
|
||||||
link := s.getLink(inbound, client.Email)
|
link := s.getLink(inbound, client.Email)
|
||||||
result = append(result, link)
|
result = append(result, link)
|
||||||
ct := s.getClientTraffics(inbound.ClientStats, client.Email)
|
ct := s.getClientTraffics(inbound.ClientStats, client.Email)
|
||||||
@@ -111,6 +115,7 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
traffic.Enable = hasEnabledClient
|
||||||
return result, lastOnline, traffic, nil
|
return result, lastOnline, traffic, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,6 +1309,7 @@ type PageData struct {
|
|||||||
Host string
|
Host string
|
||||||
BasePath string
|
BasePath string
|
||||||
SId string
|
SId string
|
||||||
|
Enabled bool
|
||||||
Download string
|
Download string
|
||||||
Upload string
|
Upload string
|
||||||
Total string
|
Total string
|
||||||
@@ -1453,6 +1459,7 @@ func (s *SubService) BuildPageData(subId string, hostHeader string, traffic xray
|
|||||||
Host: hostHeader,
|
Host: hostHeader,
|
||||||
BasePath: basePath,
|
BasePath: basePath,
|
||||||
SId: subId,
|
SId: subId,
|
||||||
|
Enabled: traffic.Enable,
|
||||||
Download: download,
|
Download: download,
|
||||||
Upload: upload,
|
Upload: upload,
|
||||||
Total: total,
|
Total: total,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
sId: el.getAttribute('data-sid') || '',
|
sId: el.getAttribute('data-sid') || '',
|
||||||
|
enabled: (el.getAttribute('data-enabled') || '').toLowerCase() === 'true',
|
||||||
subUrl: el.getAttribute('data-sub-url') || '',
|
subUrl: el.getAttribute('data-sub-url') || '',
|
||||||
subJsonUrl: el.getAttribute('data-subjson-url') || '',
|
subJsonUrl: el.getAttribute('data-subjson-url') || '',
|
||||||
subClashUrl: el.getAttribute('data-subclash-url') || '',
|
subClashUrl: el.getAttribute('data-subclash-url') || '',
|
||||||
@@ -128,9 +129,10 @@
|
|||||||
},
|
},
|
||||||
isActive() {
|
isActive() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
const enabledOk = this.app.enabled;
|
||||||
const expiryOk = !this.app.expireMs || this.app.expireMs >= now;
|
const expiryOk = !this.app.expireMs || this.app.expireMs >= now;
|
||||||
const trafficOk = !this.app.totalByte || (this.app.uploadByte + this.app.downloadByte) <= this.app.totalByte;
|
const trafficOk = !this.app.totalByte || (this.app.uploadByte + this.app.downloadByte) <= this.app.totalByte;
|
||||||
return expiryOk && trafficOk;
|
return enabledOk && expiryOk && trafficOk;
|
||||||
},
|
},
|
||||||
shadowrocketUrl() {
|
shadowrocketUrl() {
|
||||||
const rawUrl = this.app.subUrl + '?flag=shadowrocket';
|
const rawUrl = this.app.subUrl + '?flag=shadowrocket';
|
||||||
|
|||||||
@@ -153,7 +153,10 @@
|
|||||||
app.sId
|
app.sId
|
||||||
]]</a-descriptions-item>
|
]]</a-descriptions-item>
|
||||||
<a-descriptions-item label='{{ i18n "subscription.status" }}'>
|
<a-descriptions-item label='{{ i18n "subscription.status" }}'>
|
||||||
<template v-if="isUnlimited">
|
<template v-if="!app.enabled">
|
||||||
|
<a-tag color="red">{{ i18n "subscription.inactive" }}</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="isUnlimited">
|
||||||
<a-tag color="purple">{{ i18n
|
<a-tag color="purple">{{ i18n
|
||||||
"subscription.unlimited" }}</a-tag>
|
"subscription.unlimited" }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
@@ -275,7 +278,7 @@
|
|||||||
data-subclash-url="{{ .subClashUrl }}" data-download="{{ .download }}" data-upload="{{ .upload }}"
|
data-subclash-url="{{ .subClashUrl }}" data-download="{{ .download }}" data-upload="{{ .upload }}"
|
||||||
data-used="{{ .used }}" data-total="{{ .total }}" data-remained="{{ .remained }}" data-expire="{{ .expire }}"
|
data-used="{{ .used }}" data-total="{{ .total }}" data-remained="{{ .remained }}" data-expire="{{ .expire }}"
|
||||||
data-lastonline="{{ .lastOnline }}" data-downloadbyte="{{ .downloadByte }}" data-uploadbyte="{{ .uploadByte }}"
|
data-lastonline="{{ .lastOnline }}" data-downloadbyte="{{ .downloadByte }}" data-uploadbyte="{{ .uploadByte }}"
|
||||||
data-totalbyte="{{ .totalByte }}" data-datepicker="{{ .datepicker }}"></template>
|
data-totalbyte="{{ .totalByte }}" data-datepicker="{{ .datepicker }}" data-enabled="{{ .enabled }}"></template>
|
||||||
<textarea id="subscription-links" style="display:none">{{ range .result }}{{ . }}
|
<textarea id="subscription-links" style="display:none">{{ range .result }}{{ . }}
|
||||||
{{ end }}</textarea>
|
{{ end }}</textarea>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user