Files
admin-ui/src/views/assets/operation/count/component/scopeSelectDialog.vue

314 lines
7.5 KiB
Vue
Raw Normal View History

<template>
<el-dialog
v-model="visible"
:title="dialogTitle"
width="800px"
:close-on-click-modal="false"
@close="handleClose"
>
<!-- 搜索栏 -->
<div class="search-bar">
<el-input
v-model="searchKeyword"
placeholder="请输入关键词搜索"
clearable
style="width: 300px"
@keyup.enter="handleSearch"
>
<template #append>
<el-button @click="handleSearch">
<el-icon><ele-Search /></el-icon>
</el-button>
</template>
</el-input>
</div>
<!-- 数据表格 -->
<el-table
ref="tableRef"
:data="tableData"
v-loading="loading"
border
style="width: 100%; margin-top: 15px"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="name" :label="getColumnLabel()" min-width="200" show-overflow-tooltip />
<el-table-column prop="code" label="编码" width="150" show-overflow-tooltip v-if="scope <= 2" />
</el-table>
<!-- 分页 -->
<div class="pagination-box">
<el-pagination
v-model:current-page="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
<!-- 已选项展示 -->
<div class="selected-box" v-if="selectedItems.length > 0">
<span class="selected-label">已选择 {{ selectedItems.length }} </span>
<el-tag
v-for="item in selectedItems"
:key="item.id"
size="small"
closable
style="margin-right: 4px; margin-bottom: 4px"
@close="removeSelected(item)"
>
{{ item.name }}
</el-tag>
</div>
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { listWarehouses } from '/@/api/assets/warehouse';
import { listZones } from '/@/api/assets/zone';
import { listLocations } from '/@/api/assets/location';
const emit = defineEmits(['confirm']);
const visible = ref(false);
const loading = ref(false);
const scope = ref(1); // 1-仓库 2-库区 3-库位
const searchKeyword = ref('');
const tableData = ref<any[]>([]);
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
const tableRef = ref();
// 已选项
const selectedItems = ref<any[]>([]);
// 父级ID库区需要仓库ID库位需要库区ID
const parentWarehouseIds = ref<string[]>([]);
const parentZoneIds = ref<string[]>([]);
// 弹窗标题
const dialogTitle = computed(() => {
const titles: Record<number, string> = {
1: '选择仓库',
2: '选择库区',
3: '选择库位',
};
return titles[scope.value] || '选择';
});
// 获取列标题
const getColumnLabel = () => {
const labels: Record<number, string> = {
1: '仓库名称',
2: '库区名称',
3: '库位名称',
};
return labels[scope.value] || '名称';
};
// 打开弹窗
const open = async (data: {
scope: number;
selectedIds: string[];
selectedNames: string[];
warehouseIds?: string[];
zoneIds?: string[];
}) => {
scope.value = data.scope;
parentWarehouseIds.value = data.warehouseIds || [];
parentZoneIds.value = data.zoneIds || [];
// 恢复已选项
selectedItems.value = data.selectedIds.map((id, idx) => ({
id,
name: data.selectedNames[idx] || id,
}));
searchKeyword.value = '';
pageNum.value = 1;
visible.value = true;
await loadData();
};
// 加载数据
const loadData = async () => {
loading.value = true;
try {
let res: any;
const params = {
keyword: searchKeyword.value,
pageNum: pageNum.value,
pageSize: pageSize.value,
};
if (scope.value === 1) {
// 加载仓库
res = await listWarehouses(params);
const list = res.data?.list || [];
tableData.value = list.map((item: any) => ({
id: item.id,
name: item.warehouseName || item.name,
code: item.warehouseCode || item.code,
}));
total.value = res.data?.total || 0;
} else if (scope.value === 2) {
// 加载库区
if (parentWarehouseIds.value.length === 0) {
tableData.value = [];
total.value = 0;
return;
}
const allZones: any[] = [];
let totalCount = 0;
for (const warehouseId of parentWarehouseIds.value) {
res = await listZones({ ...params, warehouseId });
const list = res.data?.list || res.data?.items || res.data || [];
const zones = (Array.isArray(list) ? list : []).map((item: any) => ({
id: item.id || item._id,
name: item.zoneName || item.name,
code: item.zoneCode || item.code,
}));
allZones.push(...zones);
totalCount += res.data?.total || zones.length;
}
tableData.value = allZones;
total.value = totalCount;
} else if (scope.value === 3) {
// 加载库位
if (parentZoneIds.value.length === 0) {
tableData.value = [];
total.value = 0;
return;
}
const allLocations: any[] = [];
let totalCount = 0;
for (const zoneId of parentZoneIds.value) {
res = await listLocations({ ...params, zoneId });
const list = res.data?.list || res.data?.items || res.data || [];
const locations = (Array.isArray(list) ? list : []).map((item: any) => ({
id: item.id || item._id,
name: item.locationName || item.name,
code: item.locationCode || item.code,
}));
allLocations.push(...locations);
totalCount += res.data?.total || locations.length;
}
tableData.value = allLocations;
total.value = totalCount;
}
// 恢复选中状态
setTimeout(() => {
tableData.value.forEach((row: any) => {
if (selectedItems.value.some(item => item.id === row.id)) {
tableRef.value?.toggleRowSelection(row, true);
}
});
}, 0);
} catch (error) {
console.error('加载数据失败:', error);
} finally {
loading.value = false;
}
};
// 搜索
const handleSearch = () => {
pageNum.value = 1;
loadData();
};
// 分页大小变化
const handleSizeChange = () => {
pageNum.value = 1;
loadData();
};
// 页码变化
const handleCurrentChange = () => {
loadData();
};
// 选择变化
const handleSelectionChange = (selection: any[]) => {
// 合并当前页选中和之前选中的(去除当前页取消选中的)
const currentPageIds = tableData.value.map(item => item.id);
// 移除当前页的旧选中
const otherSelected = selectedItems.value.filter(item => !currentPageIds.includes(item.id));
// 添加当前页新选中
selectedItems.value = [...otherSelected, ...selection];
};
// 移除已选
const removeSelected = (item: any) => {
const idx = selectedItems.value.findIndex(i => i.id === item.id);
if (idx > -1) {
selectedItems.value.splice(idx, 1);
// 取消表格选中
const row = tableData.value.find(r => r.id === item.id);
if (row) {
tableRef.value?.toggleRowSelection(row, false);
}
}
};
// 关闭弹窗
const handleClose = () => {
visible.value = false;
};
// 确认选择
const handleConfirm = () => {
emit('confirm', {
selectedIds: selectedItems.value.map(item => item.id),
selectedNames: selectedItems.value.map(item => item.name),
});
handleClose();
};
defineExpose({
open,
});
</script>
<style scoped lang="scss">
.search-bar {
display: flex;
align-items: center;
}
.pagination-box {
display: flex;
justify-content: flex-end;
margin-top: 15px;
}
.selected-box {
margin-top: 15px;
padding: 10px;
background: #f5f7fa;
border-radius: 4px;
.selected-label {
font-size: 14px;
color: #606266;
margin-right: 8px;
}
}
</style>