mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-26 14:26:07 +00:00
feat(nodes): add distinct purple indicator when panel is online but Xray core failed (#5040)
* feat(nodes): add distinct purple indicator when panel is online but Xray core failed Currently nodes only show binary online/offline based on panel API reachability. This adds a third state: - Green: panel reachable + Xray healthy - Purple pulsing dot + "Online (Xray Error)": panel API works (management actions still available) but the node Xray process is in error or stopped. Tooltip shows the remote xrayError. - Red: unreachable (unchanged) Backend now captures xray.state + xray.errorMsg from /panel/api/server/status heartbeats and probes. New fields on Node + NodeSummary, forwarded for transitive nodes. Frontend Zod + NodeList rendering + dedicated .xray-error-dot CSS (color #722ED1) + i18n key. Color chosen purple per feedback after initial implementation. Refs: worktree xray-failed-in-nodes * fix: remove invalid JSON comment causing CI failures * chore: regenerate OpenAPI schemas and types for xray error indicators * chore: regenerate examples and schemas for xray error indicators * chore: regenerate missing openapi.json examples * fix --------- Co-authored-by: Rqzbeh <rqzbeh@users.noreply.github.com> Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
+12
-6
@@ -478,6 +478,12 @@ type Node struct {
|
||||
UptimeSecs uint64 `json:"uptimeSecs" example:"86400"`
|
||||
LastError string `json:"lastError"`
|
||||
|
||||
// XrayState and XrayError are captured from the remote node's /panel/api/server/status
|
||||
// during heartbeats. They let the central panel distinguish "panel API reachable"
|
||||
// (status=online) from "Xray core itself has failed on the node" for monitoring.
|
||||
XrayState string `json:"xrayState" gorm:"column:xray_state"`
|
||||
XrayError string `json:"xrayError" gorm:"column:xray_error"`
|
||||
|
||||
ConfigDirty bool `json:"configDirty" gorm:"default:false"`
|
||||
ConfigDirtyAt int64 `json:"configDirtyAt"`
|
||||
|
||||
@@ -514,6 +520,9 @@ type NodeSummary struct {
|
||||
LatencyMs int `json:"latencyMs"`
|
||||
PanelVersion string `json:"panelVersion"`
|
||||
XrayVersion string `json:"xrayVersion"`
|
||||
// XrayState/XrayError forwarded so masters can surface xray failure on transitive sub-nodes too.
|
||||
XrayState string `json:"xrayState"`
|
||||
XrayError string `json:"xrayError,omitempty"`
|
||||
}
|
||||
|
||||
type CustomGeoResource struct {
|
||||
@@ -713,18 +722,15 @@ type OutboundSubscription struct {
|
||||
AllowPrivate bool `json:"allowPrivate" form:"allowPrivate" gorm:"default:false"`
|
||||
TagPrefix string `json:"tagPrefix" form:"tagPrefix"`
|
||||
UpdateInterval int `json:"updateInterval" form:"updateInterval" gorm:"default:600"` // seconds between refreshes
|
||||
Priority int `json:"priority" form:"priority" gorm:"default:0"` // order among subscriptions in the merged outbounds (lower = earlier)
|
||||
Prepend bool `json:"prepend" form:"prepend" gorm:"default:false"` // place this subscription's outbounds before the manual template outbounds
|
||||
Priority int `json:"priority" form:"priority" gorm:"default:0"` // order among subscriptions in the merged outbounds (lower = earlier)
|
||||
Prepend bool `json:"prepend" form:"prepend" gorm:"default:false"` // place this subscription's outbounds before the manual template outbounds
|
||||
LastUpdated int64 `json:"lastUpdated" form:"lastUpdated"`
|
||||
LastError string `json:"lastError" form:"lastError"`
|
||||
LastFetchedOutbounds string `json:"lastFetchedOutbounds" form:"lastFetchedOutbounds" gorm:"type:text"`
|
||||
LinkIdentities string `json:"-" gorm:"type:text;column:link_identities"`
|
||||
CreatedAt int64 `json:"createdAt" gorm:"autoCreateTime:milli"`
|
||||
UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime:milli"`
|
||||
// OutboundCount is a derived count of the last fetched outbounds (not
|
||||
// persisted); List populates it so the UI can show how many outbounds a
|
||||
// subscription produced without shipping the full payload.
|
||||
OutboundCount int `json:"outboundCount" gorm:"-"`
|
||||
OutboundCount int `json:"outboundCount" gorm:"-"`
|
||||
}
|
||||
|
||||
func MergeClientRecord(existing *ClientRecord, incoming *ClientRecord) []ClientMergeConflict {
|
||||
|
||||
Reference in New Issue
Block a user