Files
Aliyun-VOD-Media-Library-Ma…/apps/macos/VODManager/VODManager/Views/AccountListView.swift
T
William d94054dd1a 迁移:SPM → Xcode 构建,String Catalog 替代 .strings,清理 web/server/docker 废弃代码
- 项目从 SPM (Sources/VODManager/) 迁移到 Xcode 构建系统 (VODManager.xcodeproj)
- 源码目录从 Sources/VODManager/ 迁移至 VODManager/VODManager/
- 用 Localizable.xcstrings 替代旧的 .lproj/Localizable.strings 文件
- 删除已废弃的 apps/web、apps/server、docker 目录及相关文档
- RTL 侧边栏修复:切语言时用 .id() 强制重建 NavigationSplitView
- 视频库无账号时不发起 API 请求和重试
- 无账号时显示 ContentUnavailableView 提示
2026-06-30 15:46:06 +06:00

169 lines
5.6 KiB
Swift

import SwiftUI
import SwiftData
struct AccountListView: View {
@EnvironmentObject var accountStore: AccountStore
@Query(sort: \Account.createdAt, order: .reverse) private var accounts: [Account]
@State private var editingAccount: Account?
@State private var showAddForm = false
@State private var errorMessage: String?
var body: some View {
VStack {
HStack {
Spacer()
Button("account.add") {
showAddForm = true
}
.buttonStyle(.borderedProminent)
}
.padding()
if let error = errorMessage {
HStack {
Text(error)
.foregroundStyle(.red)
Button {
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(error, forType: .string)
} label: {
Image(systemName: "doc.on.doc")
}
.buttonStyle(.borderless)
.help("error.copy_help")
Spacer()
}
.padding(.horizontal)
}
List(accounts) { account in
HStack {
VStack(alignment: .leading) {
Text(account.name)
.font(.headline)
Text("\(account.accessKeyId) / \(account.region)")
.font(.caption)
.foregroundStyle(.secondary)
}
Spacer()
if account.isActive {
Text("account.active")
.font(.caption)
.foregroundStyle(.green)
} else {
Button("btn.switch") {
Task { await accountStore.switchActive(account) }
}
.buttonStyle(.borderless)
}
Button("btn.edit") {
editingAccount = account
}
.buttonStyle(.borderless)
Button("btn.delete") {
Task { await accountStore.deleteAccount(account) }
}
.buttonStyle(.borderless)
.foregroundStyle(.red)
}
.padding(.vertical, 4)
}
}
.sheet(item: $editingAccount) { account in
AccountFormView(account: account)
}
.sheet(isPresented: $showAddForm) {
AccountFormView(account: nil)
}
}
}
struct AccountFormView: View {
@Environment(\.dismiss) private var dismiss
@EnvironmentObject var accountStore: AccountStore
@Query(sort: \Account.createdAt, order: .reverse) private var accounts: [Account]
var account: Account?
@State private var name = ""
@State private var accessKeyId = ""
@State private var accessKeySecret = ""
@State private var region = "cn-shanghai"
@State private var endpoint = ""
var body: some View {
VStack(alignment: .leading, spacing: 16) {
Text(account == nil ? "account.add_title" : "account.edit_title")
.font(.title2)
VStack(alignment: .leading, spacing: 12) {
Text("account.name")
TextField("account.name_placeholder", text: $name)
.textFieldStyle(.roundedBorder)
Text("account.access_key_id")
TextField("account.access_key_id_placeholder", text: $accessKeyId)
.textFieldStyle(.roundedBorder)
Text(account == nil ? "account.access_key_secret" : "account.access_key_secret_edit")
SecureField("account.access_key_secret_placeholder", text: $accessKeySecret)
.textFieldStyle(.roundedBorder)
Text("account.region")
TextField("account.region_placeholder", text: $region)
.textFieldStyle(.roundedBorder)
Text("account.endpoint")
TextField("account.endpoint_placeholder", text: $endpoint)
.textFieldStyle(.roundedBorder)
}
HStack {
Spacer()
Button("btn.cancel") {
dismiss()
}
Button("btn.save") {
Task { await save() }
}
.buttonStyle(.borderedProminent)
}
}
.padding()
.frame(minWidth: 450)
.onAppear {
if let account = account {
name = account.name
accessKeyId = account.accessKeyId
region = account.region
endpoint = account.endpoint ?? ""
}
}
}
private func save() async {
let secret = accessKeySecret.isEmpty ? (account?.accessKeySecret ?? "") : accessKeySecret
let newAccount = Account(
id: account?.id ?? UUID(),
name: name,
accessKeyId: accessKeyId,
accessKeySecret: secret,
region: region,
endpoint: endpoint.isEmpty ? nil : endpoint,
isActive: account?.isActive ?? (accounts.isEmpty ? true : false),
createdAt: account?.createdAt ?? Date(),
updatedAt: Date()
)
if account != nil {
await accountStore.updateAccount(newAccount)
} else {
await accountStore.addAccount(newAccount)
}
dismiss()
}
}