fix: 完善同事未完成的修改 — LAN 地址检测/画布删除撤销/连线删除按钮/Del 键/注释修正

- cmd/webui4frpc/main.go: 新增 primaryLANIPv4() 检测内网 LAN 地址,
  解决三台内网主机间集群发现失败 (reachableAddr 只回退到 hostname)
- internal/httpapi/handlers.go: applyCanvas 新增拓扑差异检测,
  画布删除连线时自动 RevokeTask 避免集群残留
- web/src/api.ts: 新增 addLink / deleteLink API 封装
- web/src/components/PortEdge.vue: × 删除按钮移到端口标签右上角 (绝对定位)
- web/src/views/CanvasView.vue: 启用 Del/Backspace 键删除选中连线
  (确认对话框 + 走 onDeleteEdge 逻辑), 修正注释
- embed dist 同步
This commit is contained in:
JianFeeeee
2026-08-24 01:03:14 +08:00
parent b39bd427fa
commit 2292ee7f3a
10 changed files with 258 additions and 84 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<title>webui4frpc</title>
<script type="module" crossorigin src="/assets/index-C5WLVFP2.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CL42Ur3_.css">
<script type="module" crossorigin src="/assets/index-D0MfyrKF.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D67FPIKJ.css">
</head>
<body>
<div id="app"></div>

View File

@ -184,15 +184,45 @@ func (h *Handler) applyCanvas(w http.ResponseWriter, r *http.Request, canvas *ca
// extended so a per-forward stop made on the forwards page (disabled=true)
// is not re-activated by a later canvas save. Local-only forwards are NOT
// submitted — they stay on this node.
localByName := map[string]store.Local{}
localByName := make(map[string]store.Local, len(canvas.Locals))
for _, l := range canvas.Locals {
localByName[l.Name] = l
}
remoteByName := map[string]store.Remote{}
remoteByName := make(map[string]store.Remote, len(canvas.Remotes))
for _, r := range canvas.Remotes {
remoteByName[r.Name] = r
}
// Build a set of (local, remote, remotePort) triples from the incoming
// canvas links so we can revoke any stale topology entries no longer
// present in the canvas (e.g. links that were deleted from the UI).
type triple struct{ local, remote string; port int }
canvasTriples := make(map[triple]bool, len(canvas.Links))
for _, ln := range canvas.Links {
canvasTriples[triple{ln.Local, ln.Remote, ln.RemotePort}] = true
}
if h.Ring != nil {
// Revoke topology entries that the canvas no longer references.
// Only revoke entries whose local name is known to this node (we only
// own tasks for locals we created). The topology is a ring-wide view
// and includes forwards owned by other nodes.
snap := h.Ring.Snapshot()
for _, t := range snap.Topology {
if _, ok := localByName[t.Local.Name]; !ok {
continue // local not in this node's canvas — skip
}
if t.Local.LocalOnly {
continue
}
if canvasTriples[triple{t.Local.Name, t.Remote.Name, t.Link.RemotePort}] {
continue // still in canvas — keep
}
// This forward is in the ring topology but NOT in the new canvas.
// Submit a REVOKE so the owning node cleans it up.
h.Ring.RevokeTask(t.Local, t.Remote, t.Link)
}
for _, ln := range canvas.Links {
loc, ok := localByName[ln.Local]
if !ok || loc.LocalOnly {