This commit is contained in:
csj
2026-09-13 11:46:12 +08:00
parent 11524e58c3
commit 8bc9ae8046
+27 -5
View File
@@ -706,17 +706,31 @@ struct AdminView: View {
}
} else if permissionSection == "现有授权" {
sectionCard("现有授权", icon: "person.crop.rectangle.badge.checkmark") {
Text("显示当前账号可查看的授权;撤销仅影响所选角色及范围。")
Text("显示当前账号可查看的授权;撤销仅影响所选角色及范围。列表会同时显示姓名和账户 ID,便于准确识别成员。")
.font(.callout).foregroundStyle(.secondary)
if model.grants.isEmpty { Text("暂无可显示的授权记录").foregroundStyle(.secondary) }
ForEach(model.grants) { g in
HStack {
Text("账户 \(g.userId)"); Text(g.role == "leader" ? "项目负责人" : g.role == "group" ? "组管理员" : "平台管理员")
Text("范围 #\(g.scopeId)").foregroundStyle(.secondary); Spacer()
let roleName = g.role == "leader" ? "项目负责人" : g.role == "group" ? "组管理员" : "平台管理员"
let scopeName = grantScopeName(g)
HStack(spacing: 14) {
Image(systemName: g.role == "platform" ? "crown" : "person.crop.circle")
.foregroundStyle(g.role == "platform" ? .orange : .accentColor)
.frame(width: 28)
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 8) {
Text(g.name.isEmpty ? "未设置姓名" : g.name).font(.headline)
Text(roleName).font(.caption.weight(.medium)).padding(.horizontal, 8).padding(.vertical, 4)
.background(Color.accentColor.opacity(0.12)).clipShape(Capsule())
}
Text("账户 ID\(g.userId) · \(scopeName)").font(.caption).foregroundStyle(.secondary)
}
Spacer()
if g.role != "platform" {
Button("撤销授权") { confirm("撤销账户 \(g.userId) 的这项授权?") { try await model.grant(userID: g.userId, role: g.role, scope: g.scopeId, revoke: true) } }
Button("撤销授权") { confirm("撤销\(g.name.isEmpty ? "账户 \(g.userId)" : g.name)”的\(roleName)授权?") { try await model.grant(userID: g.userId, role: g.role, scope: g.scopeId, revoke: true) } }
}
}
.padding(.vertical, 6)
Divider()
}
}
} else {
@@ -791,6 +805,14 @@ struct AdminView: View {
}
}.padding(20)
}
private func grantScopeName(_ grant: AdminGrant) -> String {
if grant.role == "platform" { return "全部项目与范围" }
if grant.role == "leader" {
return "项目:" + (model.access?.projects.first { $0.id == grant.scopeId }?.name ?? "范围 #\(grant.scopeId)")
}
return "组:" + (model.access?.groups.first { $0.id == grant.scopeId }?.label ?? "范围 #\(grant.scopeId)")
}
private var filteredAudit: [AdminAudit] {
model.audit.filter { AdminDisplayFilter.matches(auditSearch, fields: [$0.actorId, $0.action, $0.resourceId, $0.detail, $0.date]) }
}