diff --git a/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
index b2ee742..5143a7d 100644
--- a/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ b/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -82,36 +82,6 @@
endingLineNumber = "243"
landmarkName = "HistoryView"
landmarkType = "14">
-
-
-
-
-
-
diff --git a/MyQrCode/Views/HistoryView.swift b/MyQrCode/Views/HistoryView.swift
index 57a6bc6..a6292b9 100644
--- a/MyQrCode/Views/HistoryView.swift
+++ b/MyQrCode/Views/HistoryView.swift
@@ -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 = []
enum HistoryFilter: String, CaseIterable {
case all = "all"
@@ -107,34 +109,68 @@ struct HistoryView: View {
.navigationTitle("历史记录")
.navigationBarTitleDisplayMode(.large)
.toolbar {
- ToolbarItem(placement: .navigationBarLeading) {
- Button(action: {
- showingClearAlert = true
- }) {
- Image(systemName: "trash")
- .foregroundColor(.red)
- }
- .disabled(coreDataManager.fetchHistoryItems().isEmpty)
- }
-
ToolbarItem(placement: .navigationBarTrailing) {
- Button(action: {
- showingCreateSheet = true
- }) {
- Image(systemName: "plus")
+ 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: {
+ enterBatchDeleteMode()
+ }) {
+ Image(systemName: "trash")
+ .foregroundColor(.red)
+ }
+ }
+
+ Button(action: {
+ showingCreateSheet = true
+ }) {
+ Image(systemName: "plus")
+ }
+ }
}
}
}
.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,
@@ -495,4 +596,76 @@ struct HistoryItemRow: View {
formatter.timeStyle = .short
return formatter.string(from: date)
}
-}
\ No newline at end of file
+}
+
+// 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
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file