From 728066030b2e248feaed4a0751a68bfbebba7517 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Thu, 26 Mar 2026 14:19:07 +0800 Subject: [PATCH] fix network pop --- punchnet/Views/Network/NetworkMenuView.swift | 131 +++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 punchnet/Views/Network/NetworkMenuView.swift diff --git a/punchnet/Views/Network/NetworkMenuView.swift b/punchnet/Views/Network/NetworkMenuView.swift new file mode 100644 index 0000000..a0f7068 --- /dev/null +++ b/punchnet/Views/Network/NetworkMenuView.swift @@ -0,0 +1,131 @@ +import SwiftUI + +/// 弹出菜单主容器 +struct NetworkMenuPopup: View { + @Binding var isPresented: Bool + @State private var isNetworkEnabled = true + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + // 1. 顶部用户信息区 (不响应悬停) + HStack(spacing: 12) { + Image(systemName: "person.fill") + .font(.system(size: 14)) + .frame(width: 34, height: 34) + .background(Color.gray.opacity(0.1)) + .clipShape(Circle()) + + Text("test3") + .font(.system(size: 15, weight: .medium)) + } + .padding(.horizontal, 16) + .padding(.vertical, 16) + + Divider().opacity(0.3).padding(.horizontal, 16) + + // 2. 菜单功能列表 + VStack(spacing: 4) { + NetworkMenuRow(title: "管理平台") + .onTapGesture { + print("点击管理平台") + } + + NetworkMenuRow(title: "我的网络", subtitle: "test的网络") { + Toggle("", isOn: $isNetworkEnabled) + .toggleStyle(.switch) + .scaleEffect(0.65) + .labelsHidden() + .tint(Color(red: 0.15, green: 0.2, blue: 0.3)) + } + + NetworkMenuRow(title: "出口节点", subtitle: "未选择") + + NetworkMenuRow(title: "退出登录", showArrow: false) + .onTapGesture { + withAnimation(.easeOut(duration: 0.2)) { + isPresented = false + } + } + } + .padding(6) // 为悬停的高亮背景留出呼吸感 + } + .frame(width: 240) + .background( + RoundedRectangle(cornerRadius: 14) + .fill(Color(NSColor.windowBackgroundColor)) + ) + .overlay( + RoundedRectangle(cornerRadius: 14) + .stroke(Color.gray.opacity(0.1), lineWidth: 1) + ) + .shadow(color: .black.opacity(0.12), radius: 12, x: 0, y: 6) + } +} + +/// 菜单行组件 (支持 Hover 效果) +struct NetworkMenuRow: View { + let title: String + var subtitle: String? = nil + var showArrow: Bool = true + var rightContent: RightContent? + + @State private var isHovering = false // 内部维护悬停状态 + + init(title: String, subtitle: String? = nil, showArrow: Bool = true) where RightContent == EmptyView { + self.init(title: title, subtitle: subtitle, showArrow: showArrow) { + EmptyView() + } + } + + init(title: String, subtitle: String? = nil, showArrow: Bool = true, @ViewBuilder rightContent: () -> RightContent? = { nil }) { + self.title = title + self.subtitle = subtitle + self.showArrow = showArrow + self.rightContent = rightContent() + } + + var body: some View { + HStack(spacing: 0) { + VStack(alignment: .leading, spacing: 2) { + Text(title) + .font(.system(size: 13.5)) + .foregroundColor(.primary) + if let sub = subtitle { + Text(sub) + .font(.system(size: 11.5)) + .foregroundColor(.secondary) + } + } + + Spacer() + + // 右侧内容 + if let content = rightContent { + content + } + + // 右侧箭头 + if showArrow { + Image(systemName: "chevron.right") + .font(.system(size: 9, weight: .bold)) + .foregroundColor(.secondary.opacity(0.4)) + .padding(.leading, 6) + } + } + .padding(.horizontal, 12) + .padding(.vertical, 10) + // --- 悬停效果实现 --- + .background( + RoundedRectangle(cornerRadius: 8) + .fill(isHovering ? Color.gray.opacity(0.12) : Color.clear) + ) + .onHover { hovering in + withAnimation(.easeInOut(duration: 0.15)) { + isHovering = hovering + } + } + // ------------------ + .contentShape(Rectangle()) + } + +}