feat(web): cluster page optimized — self/leader/phase badges, ring arrow, create vs revoke command styling, topology owner highlight, colored log kinds, self highlights

This commit is contained in:
2026-08-18 09:54:29 +08:00
parent 40980944e5
commit 86b265637d
6 changed files with 94 additions and 53 deletions

View File

@ -47,6 +47,8 @@ type Engine struct {
lastLogSent int64
// lastRingStart time of the previous cycle launch (leader throttle).
lastRingStart time.Time
// curPhase tracks the most recently processed token phase (frontend).
curPhase int
}
// NewEngine builds the engine; state holds this node as initial leader unless
@ -189,6 +191,7 @@ func (e *Engine) phase2(ctx context.Context, tk *Token) error {
// OnToken receives the token: process by phase, return updated token.
func (e *Engine) OnToken(ctx context.Context, tk *Token) (*Token, error) {
e.curPhase = tk.Phase
log.Printf("ring[%s] OnToken cycle=%d phase=%d passed=%v", e.ID, tk.Cycle, tk.Phase, tk.Passed)
switch tk.Phase {
case PhaseCollect:
@ -227,8 +230,10 @@ func (e *Engine) Forward(ctx context.Context, tk *Token) error {
// Snapshot returns a serializable view of the ring for the frontend.
type RingSnapshot struct {
SelfID string `json:"selfId"`
LeaderID string `json:"leaderId"`
Cycle int64 `json:"cycle"`
Phase int `json:"phase"`
RoundDelay int64 `json:"roundDelayMs"`
Nodes []Node `json:"nodes"`
Pending []*Task `json:"pending"`
@ -236,10 +241,19 @@ type RingSnapshot struct {
Log []LogEntry `json:"log,omitempty"`
}
func (e *Engine) currentPhase() int {
if e.curPhase == 0 {
return PhaseCollect
}
return e.curPhase
}
func (e *Engine) Snapshot() *RingSnapshot {
snap := &RingSnapshot{
SelfID: e.ID,
LeaderID: e.state.LeaderID,
Cycle: e.state.Cycle,
Phase: e.currentPhase(),
RoundDelay: e.state.RoundDelay.Milliseconds(),
Nodes: e.state.Nodes,
Pending: e.state.PendingList(),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,8 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webui-frpc</title>
<script type="module" crossorigin src="/assets/index-traMph4r.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CkgfmeCs.css">
<script type="module" crossorigin src="/assets/index-CNe69otc.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Cq7Ykgzy.css">
</head>
<body>
<div id="app"></div>