feat(warehouse): implement bulk delete and multi-level rule-based batch generation for locations

This commit is contained in:
DXC
2026-04-02 10:55:17 +08:00
parent 84e615baf6
commit e28326b2e4
3 changed files with 331 additions and 2 deletions

View File

@ -75,6 +75,12 @@
<el-button type="primary" @click="handleAddTopLevel" :icon="Plus">
新增顶级区域
</el-button>
<el-button type="success" @click="openBatchGenerate" :icon="Plus">
批量生成
</el-button>
<el-button type="danger" @click="handleBatchDelete" :disabled="selectedIds.length === 0" :icon="Delete">
批量删除 {{ selectedIds.length > 0 ? `(${selectedIds.length})` : '' }}
</el-button>
</div>
<el-scrollbar height="450px">
<el-tree
@ -84,6 +90,8 @@
:props="treeProps"
:expand-on-click-node="false"
:default-expand-all="false"
show-checkbox
@check="handleTreeCheck"
>
<template #default="{ node, data }">
<div class="tree-node">
@ -143,11 +151,54 @@
</template>
</el-dialog>
<!-- 批量生成库位弹窗 -->
<el-dialog v-model="batchGenerateVisible" title="批量生成库位" width="600px">
<el-form :model="batchGenerateForm" label-width="100px">
<el-form-item label="父级库位">
<el-input :value="batchGenerateForm.parentName" disabled />
<el-button link size="small" @click="batchGenerateForm.parent_id = null; batchGenerateForm.parentName = '无(顶级)'">清空选择</el-button>
</el-form-item>
<el-divider>层级规则按顺序生成</el-divider>
<div v-for="(rule, index) in batchGenerateForm.rules" :key="index" class="rule-item">
<el-row :gutter="10">
<el-col :span="6">
<el-input v-model="rule.prefix" placeholder="前缀" />
</el-col>
<el-col :span="5">
<el-input-number v-model="rule.start" :min="1" placeholder="起始" style="width: 100%" />
</el-col>
<el-col :span="5">
<el-input-number v-model="rule.end" :min="1" placeholder="结束" style="width: 100%" />
</el-col>
<el-col :span="4">
<el-input-number v-model="rule.pad" :min="1" :max="5" placeholder="补零" style="width: 100%" />
</el-col>
<el-col :span="4">
<el-button type="danger" :icon="Delete" @click="batchGenerateForm.rules.splice(index, 1)" />
</el-col>
</el-row>
</div>
<el-button type="primary" plain @click="batchGenerateForm.rules.push({ prefix: '', start: 1, end: 10, pad: 1 })" :icon="Plus">
添加层级
</el-button>
<div class="batch-preview">
<span v-if="previewCount > 0">即将生成 <strong>{{ previewCount }}</strong> 个库位</span>
<span v-else>请完善规则</span>
</div>
</el-form>
<template #footer>
<el-button @click="batchGenerateVisible = false">取消</el-button>
<el-button type="primary" @click="handleBatchGenerate" :loading="batchLoading" :disabled="previewCount === 0 || previewCount > 3000">
生成 {{ previewCount > 3000 ? '(超限)' : '' }}
</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ref, reactive, computed } from 'vue'
import { useRouter } from 'vue-router'
// 1. 引入 User Store
import { useUserStore } from '@/stores/user'
@ -155,7 +206,7 @@ import { useUserStore } from '@/stores/user'
import { Box, TrendCharts, ShoppingCart, Operation, Setting, Location, Plus, Edit, Delete } from '@element-plus/icons-vue'
import { getPrinterConfig, updatePrinterConfig } from '@/api/common/print'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getWarehouseTree, createWarehouse, updateWarehouse, deleteWarehouse } from '@/api/common/warehouse'
import { getWarehouseTree, createWarehouse, updateWarehouse, deleteWarehouse, batchDeleteWarehouse, batchGenerateWarehouse } from '@/api/common/warehouse'
const router = useRouter()
// 2. 实例化 store
@ -249,6 +300,93 @@ const locationForm = reactive({
})
const locationLoading = ref(false)
// 批量删除相关
const selectedIds = ref<number[]>([])
const handleTreeCheck = (data: any, checked: any) => {
selectedIds.value = checked.checkedKeys
}
const handleBatchDelete = async () => {
if (selectedIds.value.length === 0) {
ElMessage.warning('请先选择要删除的库位')
return
}
try {
await ElMessageBox.confirm(
`确定要删除选中的 ${selectedIds.value.length} 个库位吗?该操作将同时删除所有子库位。`,
'警告',
{ type: 'warning', confirmButtonText: '确定', cancelButtonText: '取消' }
)
const res = await batchDeleteWarehouse(selectedIds.value)
if (res.code === 200) {
ElMessage.success('批量删除成功')
selectedIds.value = []
await loadWarehouseTree()
} else {
ElMessage.error(res.msg || '删除失败')
}
} catch (e) {
// 用户取消
}
}
// 批量生成相关
const batchGenerateVisible = ref(false)
const batchGenerateForm = reactive({
parent_id: null as number | null,
parentName: '无(顶级)',
rules: [{ prefix: '', start: 1, end: 10, pad: 1 }] as { prefix: string, start: number, end: number, pad: number }[]
})
const batchLoading = ref(false)
const previewCount = computed(() => {
let count = 1
for (const rule of batchGenerateForm.rules) {
if (rule.start && rule.end && rule.start <= rule.end) {
count *= (rule.end - rule.start + 1)
} else {
return 0
}
}
return count
})
const openBatchGenerate = () => {
batchGenerateForm.parent_id = null
batchGenerateForm.parentName = '无(顶级)'
batchGenerateForm.rules = [{ prefix: '', start: 1, end: 10, pad: 1 }]
batchGenerateVisible.value = true
}
const handleBatchGenerate = async () => {
if (previewCount.value === 0 || previewCount.value > 3000) {
ElMessage.warning('生成数量无效或超过限制')
return
}
try {
batchLoading.value = true
const res = await batchGenerateWarehouse({
parent_id: batchGenerateForm.parent_id,
rules: batchGenerateForm.rules
})
if (res.code === 200) {
ElMessage.success(`生成成功,共生成 ${res.data.generated_count} 个库位`)
batchGenerateVisible.value = false
await loadWarehouseTree()
} else {
ElMessage.error(res.msg || '生成失败')
}
} catch (e) {
ElMessage.error('请求异常')
} finally {
batchLoading.value = false
}
}
// 打开库位管理弹窗
const openWarehouseDialog = async () => {
await loadWarehouseTree()
@ -466,4 +604,23 @@ const handleNav = (path: string) => {
display: flex;
gap: 5px;
}
/* 批量生成规则样式 */
.rule-item {
margin-bottom: 10px;
padding: 10px;
background: #f5f7fa;
border-radius: 4px;
}
.batch-preview {
margin-top: 15px;
padding: 10px;
text-align: center;
background: #ecf5ff;
border-radius: 4px;
}
.batch-preview strong {
color: #409eff;
font-size: 16px;
}
</style>