fix settings

This commit is contained in:
anlicheng 2026-03-19 23:14:53 +08:00
parent a62d531493
commit 0dcccf445e
5 changed files with 212 additions and 156 deletions

View File

@ -7,9 +7,9 @@
import SwiftUI import SwiftUI
struct SettingsAccountView: View { struct SettingsAccountView: View {
@State var state: SettingsState = SettingsState()
@Environment(UserContext.self) var userContext: UserContext @Environment(UserContext.self) var userContext: UserContext
@Environment(\.openWindow) var openWindow @Environment(\.openWindow) var openWindow
@Environment(\.openURL) var openURL
var body: some View { var body: some View {
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
@ -43,40 +43,41 @@ struct SettingsAccountView: View {
// MARK: - // MARK: -
sectionHeader(title: "网络配置", icon: "network") sectionHeader(title: "网络配置", icon: "network")
if let networkSession = userContext.networkSession {
VStack(spacing: 16) { VStack(spacing: 16) {
HStack { HStack {
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
Text("默认网络") Text("网络")
.font(.subheadline) .font(.subheadline)
.foregroundColor(.secondary) .foregroundColor(.secondary)
Text(state.selectedNetwork.name) Text(networkSession.networkName)
.font(.headline) .font(.headline)
} }
Spacer() Spacer()
//
Menu { // Menu {
ForEach(state.networks, id: \.id) { network in // ForEach(state.networks, id: \.id) { network in
Button(network.name) { // Button(network.name) {
self.state.selectedNetwork = network // self.state.selectedNetwork = network
} // }
} // }
} label: { // } label: {
Text("切换网络") // Text("")
.font(.subheadline) // .font(.subheadline)
.padding(.horizontal, 12) // .padding(.horizontal, 12)
.padding(.vertical, 6) // .padding(.vertical, 6)
.background(Capsule().fill(Color.blue.opacity(0.1))) // .background(Capsule().fill(Color.blue.opacity(0.1)))
} // }
.buttonStyle(.plain) // .buttonStyle(.plain)
} }
Divider() Divider()
HStack { HStack {
Button { Button {
self.openNetworkUrl(url: networkSession.networkUrl)
} label: { } label: {
Label("进入管理平台", systemImage: "arrow.up.right.square") Label("进入管理平台", systemImage: "arrow.up.right.square")
} }
@ -86,7 +87,7 @@ struct SettingsAccountView: View {
Spacer() Spacer()
Button("查看详情") { Button("查看详情") {
self.openNetworkUrl(url: networkSession.networkUrl)
} }
.buttonStyle(.bordered) .buttonStyle(.bordered)
.controlSize(.small) .controlSize(.small)
@ -96,10 +97,24 @@ struct SettingsAccountView: View {
.background(Color.primary.opacity(0.03)) .background(Color.primary.opacity(0.03))
.cornerRadius(12) .cornerRadius(12)
} }
}
.frame(maxWidth: 600) // .frame(maxWidth: 600) //
} }
} }
private func openNetworkUrl(url: String) {
if let url = URL(string: url) {
openURL(url) { accepted in
if accepted {
print("浏览器已成功打开")
} else {
print("打开失败(可能是 URL 格式错误)")
}
}
}
}
// //
private func openMainWindow(id: String) { private func openMainWindow(id: String) {
let window = NSApp.windows.first { win in let window = NSApp.windows.first { win in

View File

@ -1,83 +1,174 @@
// //
// SettingsNetworkView.swift // SettingsNetworkView 2.swift
// punchnet // punchnet
// //
// Created by on 2026/1/19. // Created by on 2026/3/19.
// //
import SwiftUI import SwiftUI
struct SettingsNetworkView: View { struct SettingsNetworkView: View {
@State var state: SettingsState = SettingsState() @Environment(UserContext.self) var userContext: UserContext
@State private var selectedExitNode: UserContext.NetworkSession.ExitNode?
var body: some View { var body: some View {
VStack(alignment: .leading) { ScrollView(.vertical, showsIndicators: false) {
Text("网络") VStack(alignment: .leading, spacing: 24) {
HStack(alignment: .top) { // MARK: -
Text("默认网络") networkSectionHeader(title: "连接设置", icon: "wifi.router.fill")
VStack(alignment: .leading) { if let networkSession = userContext.networkSession {
VStack(spacing: 0) {
// //
// NetworkRow(title: "", value: state.selectedNetwork.name) {
// Menu {
// ForEach(state.networks, id: \.id) { network in
// Button(network.name) {
// self.state.selectedNetwork = network
// }
// }
// } label: {
// actionLabel(text: "")
// }
// .buttonStyle(.plain)
// }
//
// Divider().padding(.leading, 16)
//
NetworkRow(title: "出口节点", value: selectedExitNode?.nodeName ?? "") {
Menu { Menu {
ForEach(state.networks, id: \.id) { network in ForEach(networkSession.exitNodes, id: \.uuid) { node in
Button(network.name) { Button {
self.state.selectedNetwork = network self.selectedExitNode = node
} label: {
Text(node.nodeName)
} }
} }
} label: { } label: {
Text(state.selectedNetwork.name) actionLabel(text: "更改")
.padding()
.background(Color.gray.opacity(0.2))
.cornerRadius(5)
} }
.buttonStyle(.plain)
}
}
.background(Color.primary.opacity(0.03))
.cornerRadius(12)
.overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.primary.opacity(0.05), lineWidth: 1))
}
// MARK: -
networkSectionHeader(title: "授权状态", icon: "checkmark.shield.fill")
VStack(spacing: 0) {
StatusRow(title: "当前状态", value: "有效", valueColor: .green)
Divider()
.padding(.leading, 16)
StatusRow(title: "有效期", value: "临时 (至断开连接)", valueColor: .secondary)
}
.background(Color.primary.opacity(0.03))
.cornerRadius(12)
// MARK: -
HStack(spacing: 16) {
Button {
} label: {
Label("进入管理平台", systemImage: "arrow.up.right.app")
.font(.subheadline.bold())
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
Button { Button {
} label: { } label: {
Text("进入管理平台") Text("查看诊断详情")
}
.buttonStyle(.bordered)
.controlSize(.large)
}
.padding(.top, 8)
}
.padding(32)
.frame(maxWidth: 600, alignment: .leading)
} }
} }
Button { // MARK: -
} label: {
Text("详情")
}
}
private func networkSectionHeader(title: String, icon: String) -> some View {
HStack { HStack {
Text("出口节点") Image(systemName: icon)
.foregroundColor(.blue)
.font(.system(size: 14, weight: .semibold))
Menu { Text(title)
ForEach(state.exitNodes, id: \.id) { node in .font(.system(size: 15, weight: .bold))
Button(node.name) { .foregroundColor(.secondary)
self.state.selectedExitNode = node }
.padding(.leading, 4)
}
private func actionLabel(text: String) -> some View {
Text(text)
.font(.subheadline)
.padding(.horizontal, 10)
.padding(.vertical, 4)
.background(Capsule().fill(Color.blue.opacity(0.1)))
.foregroundColor(.blue)
} }
} }
} label: { // MARK: -
Text(state.selectedExitNode.name) struct NetworkRow<Content: View>: View {
} let title: String
let value: String
let action: () -> Content
init(title: String, value: String, @ViewBuilder action: @escaping () -> Content) {
self.title = title
self.value = value
self.action = action
} }
var body: some View {
HStack { HStack {
Text("授权状态") VStack(alignment: .leading, spacing: 4) {
Text("有效") Text(title).font(.caption).foregroundColor(.secondary)
Text(value).font(.system(size: 15, weight: .medium))
}
Spacer()
action()
}
.padding(16)
}
} }
struct StatusRow: View {
let title: String
let value: String
let valueColor: Color
var body: some View {
HStack { HStack {
Text("授权有效期") Text(title)
Text("临时(至断开连接)") .font(.system(size: 14))
} .foregroundColor(.primary.opacity(0.8))
} Spacer()
Text(value)
} .font(.system(size: 14, weight: .medium))
.foregroundColor(valueColor)
}
.padding(16)
}
} }
// MARK: -
#Preview { #Preview {
SettingsNetworkView() SettingsNetworkView()
.environment(UserContext()) // UserContext
} }

View File

@ -1,54 +0,0 @@
//
// SettingsState.swift
// punchnet
//
// Created by on 2026/1/16.
//
import Foundation
import Observation
@Observable
class SettingsState {
struct Network {
var id: Int
var name: String
}
struct ExitNode {
var id: Int
var name: String
}
var networks: [Network]
var selectedNetwork: Network
var exitNodes: [ExitNode]
var selectedExitNode: ExitNode
init() {
let networks: [Network] = [
.init(id: 1, name: "测试网络12"),
.init(id: 2, name: "测试网络13"),
.init(id: 3, name: "测试网络14"),
.init(id: 4, name: "测试网络15"),
.init(id: 5, name: "xyz"),
]
self.selectedNetwork = networks[0]
self.networks = networks
let exitNodes: [ExitNode] = [
.init(id: 1, name: "出口节点1"),
.init(id: 2, name: "出口节点12"),
.init(id: 3, name: "出口节点13"),
.init(id: 4, name: "出口节点14"),
.init(id: 5, name: "出口节点15"),
]
self.selectedExitNode = exitNodes[0]
self.exitNodes = exitNodes
}
}

View File

@ -8,7 +8,6 @@ import SwiftUI
struct SettingsView: View { struct SettingsView: View {
@State private var columnVisibility: NavigationSplitViewVisibility = .all @State private var columnVisibility: NavigationSplitViewVisibility = .all
@State private var state = SettingsState()
@State private var selectedMenu: MenuItem = .accout @State private var selectedMenu: MenuItem = .accout
enum MenuItem: String, CaseIterable { enum MenuItem: String, CaseIterable {
@ -77,9 +76,9 @@ struct SettingsView: View {
// 使 ID SwiftUI transition // 使 ID SwiftUI transition
switch self.selectedMenu { switch self.selectedMenu {
case .accout: case .accout:
SettingsAccountView(state: self.state) SettingsAccountView()
case .network: case .network:
SettingsNetworkView(state: self.state) SettingsNetworkView()
case .device: case .device:
SettingsDeviceView() SettingsDeviceView()
case .system: case .system:

View File

@ -22,6 +22,7 @@ class UserContext {
// //
struct NetworkSession: Codable { struct NetworkSession: Codable {
struct ExitNode: Codable { struct ExitNode: Codable {
let uuid = UUID().uuidString
let nnid: Int let nnid: Int
let nodeName: String let nodeName: String
@ -40,6 +41,10 @@ class UserContext {
let networkDomain: String let networkDomain: String
let exitNodes: [ExitNode] let exitNodes: [ExitNode]
var networkUrl: String {
return "https://www.test.cn/id=\(self.networkId)"
}
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case accessToken = "access_token" case accessToken = "access_token"
case username case username