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()) } }