feat: 规则批量删除与多选操作
后端新增 DELETE /rule/batch,按 userId 校验规则归属,先清理标签关联再批量删除并返回实际删除数;前端规则管理表格增加多选列与批量删除按钮,补充三语文案;同步更新 README 中 AI 渠道推荐与图片记账说明。
This commit is contained in:
@@ -73,6 +73,11 @@ export function deleteRule(id: number) {
|
||||
return request.delete(`/rule/${id}`)
|
||||
}
|
||||
|
||||
/** 批量删除规则,返回实际删除数量 */
|
||||
export function batchDeleteRules(ids: number[]) {
|
||||
return request.delete('/rule/batch', { data: { ids } })
|
||||
}
|
||||
|
||||
/** 启用/停用指定规则 */
|
||||
export function toggleRuleEnabled(id: number, enabled: boolean) {
|
||||
return request.put(`/rule/${id}/enabled`, { enabled })
|
||||
|
||||
@@ -546,6 +546,10 @@ export default {
|
||||
status: { zh: '启用状态', en: 'Status', ja: '有効状態' },
|
||||
statusOn: { zh: '已启用', en: 'Enabled', ja: '有効' },
|
||||
statusOff: { zh: '已停用', en: 'Disabled', ja: '無効' },
|
||||
batchDelete: { zh: '批量删除', en: 'Batch Delete', ja: '一括削除' },
|
||||
batchDeleteNone: { zh: '请先选择要删除的规则', en: 'Please select rules to delete', ja: '削除するルールを選択してください' },
|
||||
batchDeleteConfirm: { zh: '确定删除选中的 {count} 条规则吗?', en: 'Delete the {count} selected rule(s)?', ja: '選択した {count} 件のルールを削除しますか?' },
|
||||
batchDeleted: { zh: '已删除 {count} 条规则', en: 'Deleted {count} rule(s)', ja: '{count} 件のルールを削除しました' },
|
||||
},
|
||||
|
||||
// 账单导入
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
NInput, NInputNumber, NSelect, NSwitch, NTag, NText, NCard,
|
||||
} from 'naive-ui'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { getRulePage, createRule, updateRule, deleteRule, toggleRuleEnabled } from '../api/rule'
|
||||
import { getRulePage, createRule, updateRule, deleteRule, batchDeleteRules, toggleRuleEnabled } from '../api/rule'
|
||||
import type { RuleItem } from '../api/rule'
|
||||
import { getCategoryList } from '../api/category'
|
||||
import { getTagList } from '../api/tag'
|
||||
@@ -52,6 +52,7 @@ const total = ref(0)
|
||||
const searchKeyword = ref('')
|
||||
const filterEnabled = ref<string | null>(null) // 'ON' | 'OFF' | null
|
||||
const filterType = ref<string | null>(null)
|
||||
const checkedRuleIds = ref<number[]>([]) // 表格多选选中的规则ID(用于批量删除)
|
||||
|
||||
/** AI 规则建议行(带本地 key 供表格选择使用) */
|
||||
type AiRuleRow = AiRuleSuggestion & { key: number }
|
||||
@@ -162,6 +163,8 @@ function conditionTags(row: RuleItem) {
|
||||
|
||||
/** 创建表格列配置 */
|
||||
const columns = computed<DataTableColumns<RuleItem>>(() => [
|
||||
// 多选列:用于批量操作(如批量删除)
|
||||
{ type: 'selection' },
|
||||
{
|
||||
title: t('common.name'),
|
||||
key: 'name',
|
||||
@@ -713,6 +716,31 @@ function handleDelete(id: number) {
|
||||
})
|
||||
}
|
||||
|
||||
/** 批量删除选中的规则:确认后调用接口并刷新列表 */
|
||||
function handleBatchDelete() {
|
||||
const count = checkedRuleIds.value.length
|
||||
if (count === 0) {
|
||||
message.warning(t('rule.batchDeleteNone'))
|
||||
return
|
||||
}
|
||||
dialog.warning({
|
||||
title: t('common.confirmDelete'),
|
||||
content: t('rule.batchDeleteConfirm', { count }),
|
||||
positiveText: t('common.delete'),
|
||||
negativeText: t('common.cancel'),
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
const res: any = await batchDeleteRules(checkedRuleIds.value)
|
||||
message.success(t('rule.batchDeleted', { count: res.data }))
|
||||
checkedRuleIds.value = []
|
||||
await fetchData()
|
||||
} catch (e: any) {
|
||||
message.error(e.message || t('common.deleteFailed'))
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 收支类型变化时,若已选分类类型不匹配则清空,避免保存非法组合
|
||||
watch(() => form.value.type, (type) => {
|
||||
if (form.value.categoryId && type) {
|
||||
@@ -739,6 +767,9 @@ onMounted(() => {
|
||||
<h2 style="margin: 0;">{{ t('rule.title') }}</h2>
|
||||
<NSpace>
|
||||
<NButton v-if="aiEnabled" @click="handleAiRuleOpen">{{ t('ai.rule.entry') }}</NButton>
|
||||
<NButton type="error" :disabled="checkedRuleIds.length === 0" @click="handleBatchDelete">
|
||||
{{ t('rule.batchDelete') }}
|
||||
</NButton>
|
||||
<NButton type="primary" @click="handleAdd">{{ t('rule.add') }}</NButton>
|
||||
</NSpace>
|
||||
</NSpace>
|
||||
@@ -773,11 +804,13 @@ onMounted(() => {
|
||||
</NCard>
|
||||
|
||||
<NDataTable
|
||||
v-model:checked-row-keys="checkedRuleIds"
|
||||
remote
|
||||
:columns="columns"
|
||||
:data="rules"
|
||||
:loading="loading"
|
||||
:bordered="false"
|
||||
:row-key="(row: RuleItem) => row.id"
|
||||
:pagination="pagination"
|
||||
@update:page="handlePageChange"
|
||||
@update:page-size="handlePageSizeChange"
|
||||
|
||||
Reference in New Issue
Block a user