fix settings
This commit is contained in:
parent
a62d531493
commit
0dcccf445e
@ -7,9 +7,9 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsAccountView: View {
|
||||
@State var state: SettingsState = SettingsState()
|
||||
@Environment(UserContext.self) var userContext: UserContext
|
||||
@Environment(\.openWindow) var openWindow
|
||||
@Environment(\.openURL) var openURL
|
||||
|
||||
var body: some View {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
@ -43,63 +43,78 @@ struct SettingsAccountView: View {
|
||||
// MARK: - 网络部分
|
||||
sectionHeader(title: "网络配置", icon: "network")
|
||||
|
||||
VStack(spacing: 16) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("默认网络")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
if let networkSession = userContext.networkSession {
|
||||
VStack(spacing: 16) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("网络")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
Text(state.selectedNetwork.name)
|
||||
.font(.headline)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Menu {
|
||||
ForEach(state.networks, id: \.id) { network in
|
||||
Button(network.name) {
|
||||
self.state.selectedNetwork = network
|
||||
}
|
||||
Text(networkSession.networkName)
|
||||
.font(.headline)
|
||||
}
|
||||
} label: {
|
||||
Text("切换网络")
|
||||
.font(.subheadline)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(Capsule().fill(Color.blue.opacity(0.1)))
|
||||
|
||||
Spacer()
|
||||
//
|
||||
// Menu {
|
||||
// ForEach(state.networks, id: \.id) { network in
|
||||
// Button(network.name) {
|
||||
// self.state.selectedNetwork = network
|
||||
// }
|
||||
// }
|
||||
// } label: {
|
||||
// Text("切换网络")
|
||||
// .font(.subheadline)
|
||||
// .padding(.horizontal, 12)
|
||||
// .padding(.vertical, 6)
|
||||
// .background(Capsule().fill(Color.blue.opacity(0.1)))
|
||||
// }
|
||||
// .buttonStyle(.plain)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
HStack {
|
||||
Button {
|
||||
self.openNetworkUrl(url: networkSession.networkUrl)
|
||||
} label: {
|
||||
Label("进入管理平台", systemImage: "arrow.up.right.square")
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.foregroundColor(.blue)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("查看详情") {
|
||||
self.openNetworkUrl(url: networkSession.networkUrl)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.controlSize(.small)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
HStack {
|
||||
Button {
|
||||
|
||||
} label: {
|
||||
Label("进入管理平台", systemImage: "arrow.up.right.square")
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.foregroundColor(.blue)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("查看详情") {
|
||||
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.controlSize(.small)
|
||||
}
|
||||
.padding(16)
|
||||
.background(Color.primary.opacity(0.03))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
.padding(16)
|
||||
.background(Color.primary.opacity(0.03))
|
||||
.cornerRadius(12)
|
||||
|
||||
}
|
||||
.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) {
|
||||
let window = NSApp.windows.first { win in
|
||||
|
||||
@ -1,83 +1,174 @@
|
||||
//
|
||||
// SettingsNetworkView.swift
|
||||
// SettingsNetworkView 2.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/1/19.
|
||||
// Created by 安礼成 on 2026/3/19.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
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 {
|
||||
VStack(alignment: .leading) {
|
||||
Text("网络")
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 24) {
|
||||
|
||||
HStack(alignment: .top) {
|
||||
Text("默认网络")
|
||||
// MARK: - 网络连接配置
|
||||
networkSectionHeader(title: "连接设置", icon: "wifi.router.fill")
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Menu {
|
||||
ForEach(state.networks, id: \.id) { network in
|
||||
Button(network.name) {
|
||||
self.state.selectedNetwork = network
|
||||
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 {
|
||||
ForEach(networkSession.exitNodes, id: \.uuid) { node in
|
||||
Button {
|
||||
self.selectedExitNode = node
|
||||
} label: {
|
||||
Text(node.nodeName)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
actionLabel(text: "更改")
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
} label: {
|
||||
Text(state.selectedNetwork.name)
|
||||
.padding()
|
||||
.background(Color.gray.opacity(0.2))
|
||||
.cornerRadius(5)
|
||||
|
||||
}
|
||||
.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 {
|
||||
|
||||
} label: {
|
||||
Text("进入管理平台")
|
||||
Text("查看诊断详情")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.controlSize(.large)
|
||||
}
|
||||
|
||||
Button {
|
||||
|
||||
} label: {
|
||||
Text("详情")
|
||||
}
|
||||
|
||||
.padding(.top, 8)
|
||||
}
|
||||
|
||||
|
||||
HStack {
|
||||
Text("出口节点")
|
||||
|
||||
Menu {
|
||||
ForEach(state.exitNodes, id: \.id) { node in
|
||||
Button(node.name) {
|
||||
self.state.selectedExitNode = node
|
||||
}
|
||||
}
|
||||
|
||||
} label: {
|
||||
Text(state.selectedExitNode.name)
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("授权状态")
|
||||
Text("有效")
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("授权有效期")
|
||||
Text("临时(至断开连接)")
|
||||
}
|
||||
|
||||
.padding(32)
|
||||
.frame(maxWidth: 600, alignment: .leading)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - 辅助组件
|
||||
|
||||
private func networkSectionHeader(title: String, icon: String) -> some View {
|
||||
HStack {
|
||||
Image(systemName: icon)
|
||||
.foregroundColor(.blue)
|
||||
.font(.system(size: 14, weight: .semibold))
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 15, weight: .bold))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.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)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 通用行组件
|
||||
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 {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
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 {
|
||||
Text(title)
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.primary.opacity(0.8))
|
||||
|
||||
Spacer()
|
||||
Text(value)
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.foregroundColor(valueColor)
|
||||
}
|
||||
.padding(16)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 预览辅助
|
||||
#Preview {
|
||||
SettingsNetworkView()
|
||||
.environment(UserContext()) // 确保环境中存在 UserContext
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -8,7 +8,6 @@ import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@State private var columnVisibility: NavigationSplitViewVisibility = .all
|
||||
@State private var state = SettingsState()
|
||||
@State private var selectedMenu: MenuItem = .accout
|
||||
|
||||
enum MenuItem: String, CaseIterable {
|
||||
@ -77,9 +76,9 @@ struct SettingsView: View {
|
||||
// 使用 ID 辅助 SwiftUI 识别视图切换,触发 transition
|
||||
switch self.selectedMenu {
|
||||
case .accout:
|
||||
SettingsAccountView(state: self.state)
|
||||
SettingsAccountView()
|
||||
case .network:
|
||||
SettingsNetworkView(state: self.state)
|
||||
SettingsNetworkView()
|
||||
case .device:
|
||||
SettingsDeviceView()
|
||||
case .system:
|
||||
|
||||
@ -22,6 +22,7 @@ class UserContext {
|
||||
// 登陆后的网络会话信息
|
||||
struct NetworkSession: Codable {
|
||||
struct ExitNode: Codable {
|
||||
let uuid = UUID().uuidString
|
||||
let nnid: Int
|
||||
let nodeName: String
|
||||
|
||||
@ -40,6 +41,10 @@ class UserContext {
|
||||
let networkDomain: String
|
||||
let exitNodes: [ExitNode]
|
||||
|
||||
var networkUrl: String {
|
||||
return "https://www.test.cn/id=\(self.networkId)"
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accessToken = "access_token"
|
||||
case username
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user