Merge branch 'fix/notification-to-probe-settings' into merge/v272-combined

This commit is contained in:
Muse
2026-10-24 16:35:07 +00:00
20 changed files with 671 additions and 988 deletions
@@ -6,7 +6,6 @@ import (
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"github.com/gin-gonic/gin"
@@ -152,71 +151,6 @@ func TestAgentFastReportAndConfigKeys(t *testing.T) {
}
}
// V2.0.1 ⑤: batch task creation — shared fields, auto names,
// duplicate collapse, all-or-nothing validation.
func TestProbeTasksBatch(t *testing.T) {
rig := newProbeTestRig(t)
cleanPingTasks(t)
const batchPath = "/panel/api/agent/probe-tasks/batch"
rec := rig.do(http.MethodPost, batchPath, []byte(
`{"targets":["1.1.1.1:443","8.8.8.8:53"," 1.1.1.1:443 "],"autoJoin":true}`), true)
env := decodeEnvelope(t, rec.Body.Bytes())
if !env.Success {
t.Fatalf("batch create refused: %s", env.Msg)
}
var obj struct {
IDs []int64 `json:"ids"`
}
if err := json.Unmarshal(env.Obj, &obj); err != nil || len(obj.IDs) != 2 {
t.Fatalf("batch ids = %s (err %v), want 2 ids (duplicate collapsed)", env.Obj, err)
}
tasks, err := probe.PingTasks()
if err != nil || len(tasks) != 2 {
t.Fatalf("tasks after batch = %d (err %v)", len(tasks), err)
}
for _, task := range tasks {
if task.Name != task.Target {
t.Errorf("auto name = %q, want the target %q", task.Name, task.Target)
}
if task.Interval != 60 {
t.Errorf("default interval = %d, want 60", task.Interval)
}
if !task.AutoJoin {
t.Errorf("autoJoin not carried into task %d", task.ID)
}
}
cleanPingTasks(t)
rec = rig.do(http.MethodPost, batchPath, []byte(
`{"targets":["1.1.1.1:443","8.8.8.8:53"],"name":"线路","interval":30}`), true)
env = decodeEnvelope(t, rec.Body.Bytes())
if !env.Success {
t.Fatalf("named batch refused: %s", env.Msg)
}
tasks, _ = probe.PingTasks()
if len(tasks) != 2 {
t.Fatalf("named batch tasks = %d", len(tasks))
}
for _, task := range tasks {
if !strings.HasPrefix(task.Name, "线路 · ") || task.Interval != 30 {
t.Errorf("named batch task = %+v", task)
}
}
// One bad line refuses the whole paste; nothing is created.
cleanPingTasks(t)
rec = rig.do(http.MethodPost, batchPath, []byte(
`{"targets":["1.1.1.1:443","not-a-target"]}`), true)
env = decodeEnvelope(t, rec.Body.Bytes())
if env.Success {
t.Fatal("batch with a bad target succeeded")
}
if tasks, _ := probe.PingTasks(); len(tasks) != 0 {
t.Fatalf("refused batch leaked %d tasks", len(tasks))
}
}
// V2.0.1 probe batch: the meta editor's calibration + interface pin
// fields round-trip and validate.
func TestProbeMetaCalibrationFields(t *testing.T) {
-109
View File
@@ -31,7 +31,6 @@ func NewProbeTasksController(g *gin.RouterGroup) *ProbeTasksController {
pc := &ProbeTasksController{}
g.GET("/probe-tasks", pc.listTasks)
g.PUT("/probe-tasks", pc.saveTask)
g.POST("/probe-tasks/batch", pc.saveTaskBatch)
g.DELETE("/probe-tasks/:id", pc.deleteTask)
g.POST("/probe-tasks/reorder", pc.reorderTasks)
g.PUT("/probe-tasks/by-node/:nodeId", pc.setNodeTasks)
@@ -270,114 +269,6 @@ func (pc *ProbeTasksController) saveTask(c *gin.Context) {
jsonObj(c, gin.H{"id": id}, nil)
}
// probeTaskBatchForm is the batch-create shape (V2.0.1 ⑤): many
// targets at once — already split client-side from the pasted
// lines/commas — sharing every other field. Name is a shared label:
// with several targets each task is auto-named after its target
// unless a name is given, in which case it prefixes the target
// ("<name> · <target>"); with exactly one target the name is used
// verbatim (and may be empty, falling back to the target).
type probeTaskBatchForm struct {
Targets []string `json:"targets"`
Name string `json:"name"`
Interval int64 `json:"interval"`
AutoJoin bool `json:"autoJoin"`
Region string `json:"region"`
NodeIDs []int64 `json:"nodeIds"`
}
// saveTaskBatch creates one task per target, all-or-nothing on
// validation: every form is validated before the first insert, so a
// bad line refuses the whole paste with the hub-style message
// instead of leaving a half-entered list behind.
func (pc *ProbeTasksController) saveTaskBatch(c *gin.Context) {
var form probeTaskBatchForm
if err := c.ShouldBindJSON(&form); err != nil {
jsonMsg(c, "Invalid request", err)
return
}
if form.NodeIDs == nil {
form.NodeIDs = []int64{}
}
// The batch form's interval is a shared convenience field: an
// omitted one means the standard 60 s (the single-task form
// keeps requiring an explicit value).
if form.Interval == 0 {
form.Interval = 60
}
// Split remnants and duplicates in the paste collapse here;
// order is preserved (it becomes the tasks' sort order).
seen := map[string]bool{}
targets := make([]string, 0, len(form.Targets))
for _, raw := range form.Targets {
tgt := strings.TrimSpace(raw)
if tgt == "" || seen[tgt] {
continue
}
seen[tgt] = true
targets = append(targets, tgt)
}
if len(targets) == 0 {
jsonMsg(c, "请填写目标", errRequest)
return
}
sharedName := strings.TrimSpace(form.Name)
forms := make([]probeTaskForm, 0, len(targets))
for _, tgt := range targets {
name := sharedName
switch {
case len(targets) == 1:
if name == "" {
name = tgt
}
case name == "":
name = tgt
default:
name = name + " · " + tgt
}
f := probeTaskForm{
Name: name,
Target: tgt,
Interval: form.Interval,
AutoJoin: form.AutoJoin,
Region: form.Region,
NodeIDs: form.NodeIDs,
}
if msg := validateProbeTaskForm(&f); msg != "" {
jsonMsg(c, msg, errRequest)
return
}
forms = append(forms, f)
}
bound, err := agentsByNode()
if err != nil {
jsonMsg(c, "save probe tasks failed", err)
return
}
agentIDs, refusal := resolveAgentIDs(form.NodeIDs, bound)
if refusal != "" {
jsonMsg(c, refusal, errRequest)
return
}
ids := make([]int64, 0, len(forms))
for _, f := range forms {
id, err := probe.SavePingTask(probe.PingTask{
Name: f.Name,
Target: f.Target,
Interval: f.Interval,
AutoJoin: f.AutoJoin,
Region: f.Region,
AgentIDs: agentIDs,
}, nil)
if err != nil {
probeTaskError(c, err)
return
}
ids = append(ids, id)
}
jsonObj(c, gin.H{"ids": ids}, nil)
}
func (pc *ProbeTasksController) deleteTask(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -1028,8 +1028,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -1039,17 +1037,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -1059,19 +1056,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -1101,12 +1091,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "Downlink correction (GB)",
"calHint": "Corrections are added to the counted traffic (negative values subtract) and apply to panel statistics, the public page and traffic alerts.",
"statIface": "Counted interface",
"movedHint": "Probe metadata (pricing, traffic limits, calibration…) is edited on the probe settings page.",
"goSettings": "Open probe settings",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "Batch add",
"batchPlaceholder": "One target per line, or comma-separated — host:port, e.g. 1.1.1.1:443",
"batchSubmit": "Add all",
"batchHint": "The shared fields apply to every target; leave the name empty to name each task after its target.",
"batchEmpty": "Enter at least one target",
"batchDone": "Added {{count}} probe tasks"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "Probe settings",
"statusPageTitle": "Status page settings",
"retentionDays": "History retention (days)",
"retentionHint": "How long probe history (metrics and latency) is kept.",
"fastInterval": "Fast report interval",
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat.",
"metaTitle": "Per-node probe metadata",
"metaNodePlaceholder": "Select a node"
"fastIntervalHint": "How often agents report runtime metrics; everything else still rides the 60 s heartbeat."
},
"probeNotify": {
"notifyTitle": "Notifications",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "下行校正(GB)",
"calHint": "校正值加到已统计流量上(可负数扣减),作用于面板统计、公开页与流量告警。",
"statIface": "统计网卡",
"movedHint": "探针元数据(价格、流量上限、校准等)已统一到「探针设置」页编辑。",
"goSettings": "前往探针设置",
"save": "保存状态页信息",
"saved": "状态页信息已保存",
"saveFailed": "状态页信息保存失败"
@@ -921,17 +919,16 @@
"intro": "由 agent 节点执行的 TCP 延迟探测。修改在各 agent 下一次拉取配置时生效(约 30 秒),无需重启。",
"loading": "加载中…",
"empty": "还没有探测任务,新增一个开始测延迟。",
"add": "新增探测",
"name": "名称",
"target": "目标",
"targetPlaceholder": "主机:端口,如 1.1.1.1:443",
"interval": "间隔(秒)",
"region": "地区",
"ungrouped": "未分组",
"autoJoin": "自动加入",
"autoJoinOn": "自动",
"nodes": "指派节点",
"nodesPlaceholder": "选择节点",
"selectAllNodes": "选择全部节点",
"actions": "操作",
"edit": "编辑",
"delete": "删除",
@@ -941,19 +938,12 @@
"saved": "探测任务已保存",
"deleted": "探测任务已删除",
"loadFailed": "探测任务加载失败",
"saveFailed": "操作失败",
"batchTitle": "批量添加",
"batchPlaceholder": "每行一个目标,或用逗号分隔——主机:端口,如 1.1.1.1:443",
"batchSubmit": "全部添加",
"batchHint": "共用字段对每个目标生效;名称留空时按目标自动命名。",
"batchEmpty": "至少填写一个目标",
"batchDone": "已添加 {{count}} 个探测任务"
"saveFailed": "操作失败"
}
},
"settings": {
"probeThemes": {
"title": "主题商店",
"settingsTitle": "公开状态页",
"publicPage": "公开状态页",
"publicPageHint": "关闭时,状态页及其接口只对已登录的面板开放。",
"siteName": "站点名",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "探针设置",
"statusPageTitle": "状态页设置",
"retentionDays": "历史保留(天)",
"retentionHint": "探针历史数据(指标/延迟)的保留时长。",
"fastInterval": "快报间隔",
"fastIntervalHint": "agent 上报运行时指标的频率;其余内容仍走 60 秒心跳。",
"metaTitle": "按节点探针元数据",
"metaNodePlaceholder": "选择节点"
"fastIntervalHint": "agent 上报运行时指标的频率;其余内容仍走 60 秒心跳。"
},
"probeNotify": {
"notifyTitle": "通知",
+4 -15
View File
@@ -910,8 +910,6 @@
"calDown": "下行校正(GB)",
"calHint": "校正值加到已统计流量上(可负数扣减),作用于面板统计、公开页与流量告警。",
"statIface": "统计网卡",
"movedHint": "探针元数据(价格、流量上限、校准等)已统一到「探针设置」页编辑。",
"goSettings": "前往探针设置",
"save": "Save status page info",
"saved": "Status page info saved",
"saveFailed": "Saving status page info failed"
@@ -921,17 +919,16 @@
"intro": "TCP latency probes run by agent nodes. Changes apply on each agent's next config poll (about 30 s); nothing restarts.",
"loading": "Loading…",
"empty": "No probe tasks yet. Add one to start measuring latency.",
"add": "Add probe",
"name": "Name",
"target": "Target",
"targetPlaceholder": "host:port, e.g. 1.1.1.1:443",
"interval": "Interval (s)",
"region": "Region",
"ungrouped": "Ungrouped",
"autoJoin": "Auto-join",
"autoJoinOn": "Auto",
"nodes": "Nodes",
"nodesPlaceholder": "Assign nodes",
"selectAllNodes": "Select all nodes",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
@@ -941,19 +938,12 @@
"saved": "Probe task saved",
"deleted": "Probe task deleted",
"loadFailed": "Failed to load probe tasks",
"saveFailed": "Operation failed",
"batchTitle": "批量添加",
"batchPlaceholder": "每行一个目标,或用逗号分隔——主机:端口,如 1.1.1.1:443",
"batchSubmit": "全部添加",
"batchHint": "共用字段对每个目标生效;名称留空时按目标自动命名。",
"batchEmpty": "至少填写一个目标",
"batchDone": "已添加 {{count}} 个探测任务"
"saveFailed": "Operation failed"
}
},
"settings": {
"probeThemes": {
"title": "Theme store",
"settingsTitle": "Public status page",
"publicPage": "Public page",
"publicPageHint": "When off, the status page and its API answer only to the logged-in panel.",
"siteName": "Site name",
@@ -983,12 +973,11 @@
},
"probe": {
"title": "探针设置",
"statusPageTitle": "Status page settings",
"retentionDays": "历史保留(天)",
"retentionHint": "探针历史数据(指标/延迟)的保留时长。",
"fastInterval": "快报间隔",
"fastIntervalHint": "agent 上报运行时指标的频率;其余内容仍走 60 秒心跳。",
"metaTitle": "按节点探针元数据",
"metaNodePlaceholder": "选择节点"
"fastIntervalHint": "agent 上报运行时指标的频率;其余内容仍走 60 秒心跳。"
},
"probeNotify": {
"notifyTitle": "Notifications",