@ -6,12 +6,14 @@ struct HistoryView: View {
@ State private var searchText = " "
@ State private var selectedFilter : HistoryFilter = . all
@ State private var showingCreateSheet = false
@ State private var showingClearAlert = false
@ State private var itemToDelete : HistoryItem ?
@ State private var showingDeleteAlert = false
@ State private var showingClearConfirmSheet = false
@ State private var allHistoryItems : [ HistoryItem ] = [ ]
@ State private var isLoading = false
@ State private var refreshTrigger = false
@ State private var isBatchDeleteMode = false
@ State private var selectedItemsForDelete : Set < UUID > = [ ]
enum HistoryFilter : String , CaseIterable {
case all = " all "
@ -107,17 +109,51 @@ struct HistoryView: View {
. navigationTitle ( " 历史记录 " )
. navigationBarTitleDisplayMode ( . large )
. toolbar {
ToolbarItem ( placement : . navigationBarLeading ) {
ToolbarItem ( placement : . navigationBarTrailing ) {
HStack ( spacing : 16 ) {
if isBatchDeleteMode {
// 批 量 删 除 模 式 下 的 按 钮
Button ( action : {
// 全 选 / 取 消 全 选
if selectedItemsForDelete . count = = filteredItems . count {
selectedItemsForDelete . removeAll ( )
} else {
selectedItemsForDelete = Set ( filteredItems . compactMap { $0 . id } )
}
} ) {
Image ( systemName : selectedItemsForDelete . count = = filteredItems . count ? " checkmark.rectangle.fill " : " rectangle.on.rectangle " )
. foregroundColor ( . blue )
}
Button ( action : {
if ! selectedItemsForDelete . isEmpty {
deleteSelectedItems ( )
}
} ) {
Image ( systemName : " trash.fill " )
. foregroundColor ( . red )
}
. disabled ( selectedItemsForDelete . isEmpty )
// 返 回 正 常 状 态 按 钮
Button ( action : {
exitBatchDeleteMode ( )
} ) {
Image ( systemName : " xmark.circle " )
. foregroundColor ( . gray )
}
} else {
// 正 常 模 式 下 的 按 钮
// 只 有 当 有 记 录 时 才 显 示 删 除 按 钮
if ! allHistoryItems . isEmpty {
Button ( action : {
showingClearAlert = true
enterBatchDeleteMode ( )
} ) {
Image ( systemName : " trash " )
. foregroundColor ( . red )
}
. disabled ( coreDataManager . fetchHistoryItems ( ) . isEmpty )
}
ToolbarItem ( placement : . navigationBarTrailing ) {
Button ( action : {
showingCreateSheet = true
} ) {
@ -125,16 +161,16 @@ struct HistoryView: View {
}
}
}
}
}
. sheet ( isPresented : $ showingCreateSheet ) {
CreateCodeView ( )
}
. alert ( " 清空历史记录 " , isPresented : $ showingClearAlert ) {
Button ( " 取消 " , role : . cancel ) { }
Button ( " 清空 " , role : . destructive ) {
clearHistory ( )
}
} message : {
Text ( " 确定要清空所有历史记录吗?此操作不可撤销。 " )
. sheet ( isPresented : $ showingClearConfirmSheet ) {
ClearHistoryConfirmView (
isPresented : $ showingClearConfirmSheet ,
onConfirm : clearHistory
)
}
. alert ( " 删除确认 " , isPresented : $ showingDeleteAlert ) {
Button ( " 取消 " , role : . cancel ) { }
@ -205,6 +241,47 @@ struct HistoryView: View {
showingDeleteAlert = true
}
// MARK: - 批 量 删 除 相 关 方 法
private func enterBatchDeleteMode ( ) {
isBatchDeleteMode = true
// 默 认 全 选 当 前 过 滤 后 的 项 目
selectedItemsForDelete = Set ( filteredItems . compactMap { $0 . id } )
}
private func exitBatchDeleteMode ( ) {
isBatchDeleteMode = false
selectedItemsForDelete . removeAll ( )
}
private func deleteSelectedItems ( ) {
// 获 取 选 中 的 项 目
let itemsToDelete = allHistoryItems . filter { item in
guard let id = item . id else { return false }
return selectedItemsForDelete . contains ( id )
}
// 批 量 删 除
for item in itemsToDelete {
coreDataManager . deleteHistoryItem ( item )
}
// 从 本 地 缓 存 中 移 除
allHistoryItems . removeAll { item in
guard let id = item . id else { return false }
return selectedItemsForDelete . contains ( id )
}
// 清 空 选 择 状 态 并 退 出 批 量 删 除 模 式
selectedItemsForDelete . removeAll ( )
isBatchDeleteMode = false
// 强 制 刷 新 数 据
DispatchQueue . main . async {
allHistoryItems = coreDataManager . fetchHistoryItems ( )
refreshTrigger . toggle ( )
}
}
// MARK: - 搜 索 栏
private var searchBar : some View {
HStack {
@ -265,6 +342,17 @@ struct HistoryView: View {
} ,
onDelete : {
showDeleteConfirmation ( for : item )
} ,
isBatchDeleteMode : isBatchDeleteMode ,
isSelected : selectedItemsForDelete . contains ( item . id ? ? UUID ( ) ) ,
onToggleSelection : {
if let id = item . id {
if selectedItemsForDelete . contains ( id ) {
selectedItemsForDelete . remove ( id )
} else {
selectedItemsForDelete . insert ( id )
}
}
}
)
}
@ -372,9 +460,22 @@ struct HistoryItemRow: View {
let item : HistoryItem
let onToggleFavorite : ( ) -> Void
let onDelete : ( ) -> Void
let isBatchDeleteMode : Bool
let isSelected : Bool
let onToggleSelection : ( ) -> Void
var body : some View {
HStack ( spacing : 12 ) {
// 批 量 删 除 模 式 下 的 选 择 框
if isBatchDeleteMode {
Button ( action : onToggleSelection ) {
Image ( systemName : isSelected ? " checkmark.square.fill " : " square " )
. font ( . system ( size : 20 ) )
. foregroundColor ( isSelected ? . blue : . gray )
}
. buttonStyle ( PlainButtonStyle ( ) )
}
// 类 型 图 标
VStack {
if let dataTypeString = item . dataType ,
@ -496,3 +597,75 @@ struct HistoryItemRow: View {
return formatter . string ( from : date )
}
}
// MARK: - 清 空 历 史 记 录 确 认 视 图
struct ClearHistoryConfirmView : View {
@ Binding var isPresented : Bool
let onConfirm : ( ) -> Void
var body : some View {
NavigationView {
VStack ( spacing : 20 ) {
// 警 告 图 标
Image ( systemName : " exclamationmark.triangle.fill " )
. font ( . system ( size : 50 ) )
. foregroundColor ( . red )
// 标 题
Text ( " 清空历史记录 " )
. font ( . title2 )
. fontWeight ( . bold )
// 简 单 说 明
Text ( " 此操作将删除所有历史记录,且不可撤销 " )
. font ( . body )
. foregroundColor ( . secondary )
. multilineTextAlignment ( . center )
Spacer ( )
// 按 钮 区 域
VStack ( spacing : 12 ) {
// 确 认 删 除 按 钮
Button ( action : {
onConfirm ( )
isPresented = false
} ) {
HStack {
Image ( systemName : " trash.fill " )
Text ( " 确认删除 " )
}
. frame ( maxWidth : . infinity )
. padding ( )
. background ( Color . red )
. foregroundColor ( . white )
. cornerRadius ( 10 )
}
// 取 消 按 钮
Button ( action : {
isPresented = false
} ) {
Text ( " 取消 " )
. frame ( maxWidth : . infinity )
. padding ( )
. background ( Color ( . systemGray5 ) )
. foregroundColor ( . primary )
. cornerRadius ( 10 )
}
}
}
. padding ( 20 )
. navigationTitle ( " 确认删除 " )
. navigationBarTitleDisplayMode ( . inline )
. navigationBarBackButtonHidden ( true )
. toolbar {
ToolbarItem ( placement : . navigationBarLeading ) {
Button ( " 关闭 " ) {
isPresented = false
}
}
}
}
}
}