diff --git a/docs/按狀態批量刪除鏈接前端實現說明.md b/docs/按狀態批量刪除鏈接前端實現說明.md
new file mode 100644
index 0000000..37e9c6f
--- /dev/null
+++ b/docs/按狀態批量刪除鏈接前端實現說明.md
@@ -0,0 +1,138 @@
+# 按狀態批量刪除鏈接前端實現說明
+
+## 功能概述
+在現有的鏈接生成頁面中新增了按狀態批量刪除鏈接的功能,用戶可以根據指定的狀態批量刪除自己的鏈接。
+
+## 實現內容
+
+### 1. API 接口實現
+**文件:** `src/api/links.js`
+
+新增了 `batchDeleteByStatus` 方法:
+```javascript
+// 按状态批量删除链接
+export function batchDeleteByStatus(payload) {
+ // payload: { statusList: string[], confirmDelete: boolean }
+ return http.post('/api/link/batch-delete-by-status', payload)
+}
+```
+
+### 2. UI 界面實現
+**文件:** `src/views/links/LinkGenerate.vue`
+
+#### 2.1 操作入口
+- **桌面端:** 在鏈接列表卡片頭部新增「按狀態刪除」按鈕
+- **移動端:** 在移動端操作按鈕組中新增相同功能按鈕
+
+#### 2.2 對話框界面
+- 使用 `el-dialog` 組件創建批量刪除對話框
+- 包含狀態選擇(多選框組)和確認刪除選項
+- 支持響應式設計,移動端優化顯示
+
+#### 2.3 狀態選項
+支持的鏈接狀態:
+- **NEW**: 新建
+- **USING**: 使用中
+- **LOGGED_IN**: 已登錄
+- **COMPLETED**: 已完成
+- **REFUNDED**: 已退款
+- **EXPIRED**: 已過期
+
+### 3. 業務邏輯實現
+
+#### 3.1 表單驗證
+- 狀態列表不能為空
+- 必須勾選確認刪除選項
+- 使用 Element Plus 的表單驗證規則
+
+#### 3.2 安全確認機制
+- 表單提交前進行驗證
+- 二次確認對話框顯示要刪除的狀態
+- 防止誤操作
+
+#### 3.3 結果處理
+- 顯示刪除結果統計(成功/失敗數量)
+- 失敗時顯示詳細錯誤信息
+- 自動刷新鏈接列表
+
+### 4. 響應式數據結構
+
+```javascript
+const batchDeleteByStatusDialog = reactive({
+ visible: false, // 對話框顯示狀態
+ loading: false, // 刪除操作加載狀態
+ form: {
+ statusList: [], // 選中的狀態列表
+ confirmDelete: false // 確認刪除選項
+ },
+ rules: {
+ // 表單驗證規則
+ statusList: [...],
+ confirmDelete: [...]
+ }
+})
+```
+
+### 5. 主要方法
+
+#### 5.1 `showBatchDeleteByStatusDialog()`
+- 顯示批量刪除對話框
+- 重置表單狀態
+
+#### 5.2 `closeBatchDeleteByStatusDialog()`
+- 關閉對話框
+- 清理表單數據和狀態
+
+#### 5.3 `handleBatchDeleteByStatus()`
+- 執行批量刪除操作
+- 包含完整的驗證、確認、調用API、結果處理流程
+
+## 用戶操作流程
+
+1. **打開功能:** 點擊「按狀態刪除」按鈕
+2. **選擇狀態:** 勾選要刪除的鏈接狀態(可多選)
+3. **確認操作:** 勾選確認刪除選項
+4. **提交請求:** 點擊「確認刪除」按鈕
+5. **二次確認:** 在彈出的確認對話框中確認操作
+6. **查看結果:** 系統顯示刪除結果並自動刷新列表
+
+## 錯誤處理
+
+### 客戶端驗證
+- 狀態列表為空時提示用戶選擇
+- 未確認刪除時阻止提交
+- 表單驗證失敗時顯示相應錯誤信息
+
+### 服務端錯誤
+- 網絡錯誤時顯示通用錯誤信息
+- 服務端返回的具體錯誤信息會顯示給用戶
+- 部分成功時會顯示成功和失敗的統計信息
+
+## 移動端優化
+
+### 界面適配
+- 對話框寬度自適應移動端屏幕
+- 狀態選擇框採用縱向佈局
+- 按鈕尺寸和間距針對觸摸操作優化
+
+### 樣式優化
+- 選擇框使用卡片式設計,易於點擊
+- 選中狀態有明顯的視覺反饋
+- 支持深色模式適配
+
+## 安全特性
+
+1. **權限控制:** 用戶只能刪除自己創建的鏈接
+2. **操作確認:** 雙重確認機制防止誤操作
+3. **參數驗證:** 前後端雙重驗證確保數據安全
+4. **狀態限制:** 限制可選擇的狀態類型和數量
+
+## 技術特點
+
+- **響應式設計:** 支持桌面端和移動端
+- **用戶體驗:** 操作流程清晰,反饋及時
+- **錯誤處理:** 完善的錯誤捕獲和用戶提示
+- **代碼復用:** 複用現有的 API 和組件結構
+- **維護性:** 代碼結構清晰,易於維護和擴展
+
+這個實現為用戶提供了一個安全、易用的批量刪除功能,大大提高了鏈接管理的效率。
diff --git a/src/api/links.js b/src/api/links.js
index bbf0d59..68f1bbb 100644
--- a/src/api/links.js
+++ b/src/api/links.js
@@ -32,4 +32,10 @@ export function getLinkStatus(codeNo) {
return http.get(`/api/link/${codeNo}/status`)
}
+// 按状态批量删除链接
+export function batchDeleteByStatus(payload) {
+ // payload: { statusList: string[], confirmDelete: boolean }
+ return http.post('/api/link/batch-delete-by-status', payload)
+}
+
diff --git a/src/views/links/LinkGenerate.vue b/src/views/links/LinkGenerate.vue
index 0b8dc9f..d977587 100644
--- a/src/views/links/LinkGenerate.vue
+++ b/src/views/links/LinkGenerate.vue
@@ -155,6 +155,15 @@
>
导出CSV
+
+ 按状态删除
+
@@ -178,6 +187,15 @@
导出CSV
+
+
+ 按状态删除
+
@@ -414,6 +432,54 @@
+
+
+
+
+
+
+ {{ status.label }}
+
+
+ 选择要删除的链接状态,可多选
+
+
+
+
+ 我确认要删除选中状态的所有链接,此操作不可恢复
+
+
+
+
+
+
+
+
@@ -425,7 +491,7 @@ import {
Plus, Minus, Connection, Refresh, Download,
DocumentCopy, Delete
} from '@element-plus/icons-vue'
-import { generateLinks, fetchLinks, deleteLink, batchDeleteLinks } from '@/api/links'
+import { generateLinks, fetchLinks, deleteLink, batchDeleteLinks, batchDeleteByStatus } from '@/api/links'
import { formatLinkStatus, getLinkStatusType, generateQRCodeUrl, downloadImage, copyToClipboard as copyText, exportToCSV as exportCSV, exportToExcel } from '@/utils/links'
import { LINK_CONFIG, STATUS_CONFIG, EXPORT_CONFIG } from '@/config/links'
@@ -447,6 +513,46 @@ const selectedRows = ref([])
const showBatchActions = computed(() => selectedRows.value.length > 0)
const tableRef = ref()
+// 按状态批量删除相关状态
+const batchDeleteFormRef = ref()
+const batchDeleteByStatusDialog = reactive({
+ visible: false,
+ loading: false,
+ form: {
+ statusList: [],
+ confirmDelete: false
+ },
+ rules: {
+ statusList: [
+ { required: true, message: '请选择要删除的状态', trigger: 'change' },
+ { type: 'array', min: 1, message: '至少选择一个状态', trigger: 'change' }
+ ],
+ confirmDelete: [
+ { required: true, message: '请确认删除操作', trigger: 'change' },
+ {
+ validator: (rule, value, callback) => {
+ if (!value) {
+ callback(new Error('必须确认删除操作'))
+ } else {
+ callback()
+ }
+ },
+ trigger: 'change'
+ }
+ ]
+ }
+})
+
+// 状态选项
+const statusOptions = [
+ { value: 'NEW', label: '新建' },
+ { value: 'USING', label: '使用中' },
+ { value: 'LOGGED_IN', label: '已登錄' },
+ { value: 'COMPLETED', label: '已完成' },
+ { value: 'REFUNDED', label: '已退款' },
+ { value: 'EXPIRED', label: '已過期' }
+]
+
// 生成表单
const generateForm = reactive({
times: null,
@@ -810,6 +916,77 @@ const toggleSelection = (item) => {
}
}
+// 按状态批量删除相关方法
+const showBatchDeleteByStatusDialog = () => {
+ batchDeleteByStatusDialog.visible = true
+ batchDeleteByStatusDialog.form.statusList = []
+ batchDeleteByStatusDialog.form.confirmDelete = false
+}
+
+const closeBatchDeleteByStatusDialog = () => {
+ batchDeleteByStatusDialog.visible = false
+ batchDeleteByStatusDialog.loading = false
+ batchDeleteByStatusDialog.form.statusList = []
+ batchDeleteByStatusDialog.form.confirmDelete = false
+ batchDeleteFormRef.value?.resetFields()
+}
+
+const handleBatchDeleteByStatus = async () => {
+ try {
+ // 表单验证
+ await batchDeleteFormRef.value.validate()
+
+ const { statusList, confirmDelete } = batchDeleteByStatusDialog.form
+
+ // 二次确认
+ await ElMessageBox.confirm(
+ `確定要刪除狀態為 "${statusList.map(s => statusOptions.find(opt => opt.value === s)?.label).join('、')}" 的所有鏈接嗎?此操作不可恢復!`,
+ '批量刪除確認',
+ {
+ confirmButtonText: '確定刪除',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }
+ )
+
+ batchDeleteByStatusDialog.loading = true
+
+ // 調用API
+ const response = await batchDeleteByStatus({
+ statusList,
+ confirmDelete
+ })
+
+ const result = response.data
+
+ // 顯示結果
+ if (result.allSuccess) {
+ ElMessage.success(`成功刪除 ${result.successCount} 個鏈接`)
+ } else {
+ ElMessage.warning(
+ `刪除完成:成功 ${result.successCount} 個,失敗 ${result.failedCount} 個`
+ )
+
+ // 如果有失敗的,顯示詳細信息
+ if (result.failedCount > 0 && result.failedReasons.length > 0) {
+ console.warn('刪除失敗的原因:', result.failedReasons)
+ }
+ }
+
+ // 關閉對話框並刷新列表
+ closeBatchDeleteByStatusDialog()
+ await getLinkList()
+
+ } catch (error) {
+ if (error !== 'cancel') {
+ console.error('按狀態批量刪除失敗:', error)
+ ElMessage.error(error.response?.data?.message || '批量刪除失敗')
+ }
+ } finally {
+ batchDeleteByStatusDialog.loading = false
+ }
+}
+
// 页面加载时获取数据
onMounted(() => {
checkMobile()
@@ -1259,6 +1436,26 @@ onUnmounted(() => {
padding: 0 20px 20px 20px;
text-align: center;
}
+
+ /* 按状态删除对话框移动端优化 */
+ .batch-delete-dialog :deep(.el-checkbox-group) {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ }
+
+ .batch-delete-dialog :deep(.el-checkbox) {
+ margin-right: 0;
+ padding: 8px 12px;
+ border: 1px solid #e4e7ed;
+ border-radius: 8px;
+ background: #f8f9fa;
+ }
+
+ .batch-delete-dialog :deep(.el-checkbox.is-checked) {
+ background: #ecf5ff;
+ border-color: #409eff;
+ }
}
@media (max-width: 480px) {
diff --git a/vite.config.js b/vite.config.js
index f1e8e51..7da7c15 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -27,7 +27,7 @@ export default defineConfig({
server: {
proxy: {
'/api': {
- target: 'http://192.140.164.137:18080',
+ target: 'http://127.0.0.1:18080',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api/, ''),
},