优化库位和库区管理的仓库选择交互,将下拉选择改为弹窗选择模式,新增库位必填字段验证,调整盘点管理导入功能从列表操作移至详情操作,优化查询条件从ID改为名称模糊查询

This commit is contained in:
WUSIJIAN
2026-02-28 16:03:33 +08:00
parent 95b97314a2
commit 7e2595467b
9 changed files with 607 additions and 115 deletions

View File

@@ -0,0 +1,209 @@
<template>
<el-dialog title="导入盘点" v-model="isShowDialog" width="550px" :close-on-click-modal="false" @close="onCancel">
<el-alert title="请先选择要上传的Excel文件" type="warning" :closable="false" show-icon class="mb15" />
<el-upload
ref="uploadRef"
class="upload-area"
drag
action="#"
:auto-upload="false"
:show-file-list="true"
:limit="1"
accept=".xlsx,.xls"
:on-change="handleFileChange"
:on-exceed="handleExceed"
>
<el-icon class="el-icon--upload"><ele-Upload /></el-icon>
<div class="el-upload__text">
将Excel文件拖到此处<em>点击上传</em>
</div>
</el-upload>
<div class="upload-tip">支持 .xlsx, .xls 格式文件大小不超过 10MB</div>
<div class="import-tips">
<div class="tips-title">导入说明</div>
<ul class="tips-list">
<li>1. 请先<el-link type="primary" @click="onDownloadTemplate">下载导入模板</el-link>查看数据格式</li>
<li>2. 按照模板格式准备您的盘点数据</li>
<li>3. 选择准备好的Excel文件上传</li>
<li>4. 文件编码请使用UTF-8</li>
<li>5. 文件大小不能超过 10MB</li>
</ul>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel"> </el-button>
<el-button type="primary" @click="onSubmit" :loading="submitLoading" :disabled="!selectedFile"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts">
export default {
name: 'importDialog',
};
</script>
<script setup lang="ts">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import type { UploadFile, UploadInstance, UploadRawFile } from 'element-plus';
import { exportInventoryCountTemplate, importInventoryCount } from '/@/api/assets/operation/count';
// 定义事件
const emit = defineEmits(['refresh']);
// 弹窗状态
const isShowDialog = ref(false);
const submitLoading = ref(false);
// 盘点任务ID
const countId = ref('');
// 上传组件ref
const uploadRef = ref<UploadInstance>();
// 选中的文件
const selectedFile = ref<UploadRawFile | null>(null);
// 文件变化
const handleFileChange = (file: UploadFile) => {
if (file.raw) {
// 校验文件大小
const isLt10M = file.raw.size / 1024 / 1024 < 10;
if (!isLt10M) {
ElMessage.error('文件大小不能超过 10MB');
uploadRef.value?.clearFiles();
selectedFile.value = null;
return;
}
selectedFile.value = file.raw;
}
};
// 文件超出限制
const handleExceed = () => {
ElMessage.warning('只能上传一个文件,请先删除已选文件');
};
// 下载模板
const onDownloadTemplate = async () => {
try {
const res = await exportInventoryCountTemplate();
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = '盘点模板.xlsx';
link.click();
window.URL.revokeObjectURL(url);
ElMessage.success('模板下载成功');
} catch (error) {
console.error('下载模板失败:', error);
ElMessage.error('下载模板失败');
}
};
// 打开弹窗
const openDialog = (id: string) => {
if (!id) {
ElMessage.warning('请先选择要导入的盘点任务');
return;
}
countId.value = id;
selectedFile.value = null;
uploadRef.value?.clearFiles();
isShowDialog.value = true;
};
// 取消
const onCancel = () => {
isShowDialog.value = false;
selectedFile.value = null;
uploadRef.value?.clearFiles();
};
// 提交
const onSubmit = async () => {
if (!selectedFile.value) {
ElMessage.warning('请先选择要上传的文件');
return;
}
submitLoading.value = true;
try {
const res = await importInventoryCount(countId.value, selectedFile.value);
if (res.data.code === 200) {
ElMessage.success('导入成功');
isShowDialog.value = false;
emit('refresh');
} else {
ElMessage.error(res.data.msg || '导入失败');
}
} catch (error) {
console.error('导入失败:', error);
ElMessage.error('导入失败');
} finally {
submitLoading.value = false;
uploadRef.value?.clearFiles();
selectedFile.value = null;
}
};
// 暴露方法
defineExpose({
openDialog,
});
</script>
<style scoped lang="scss">
.upload-area {
width: 100%;
:deep(.el-upload) {
width: 100%;
}
:deep(.el-upload-dragger) {
width: 100%;
height: 150px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
.upload-tip {
font-size: 12px;
color: #909399;
margin-top: 8px;
}
.import-tips {
margin-top: 20px;
padding: 15px;
background-color: #f5f7fa;
border-radius: 4px;
.tips-title {
font-size: 14px;
font-weight: bold;
color: #303133;
margin-bottom: 10px;
}
.tips-list {
margin: 0;
padding: 0;
list-style: none;
li {
font-size: 13px;
color: #606266;
line-height: 24px;
}
}
}
</style>

View File

@@ -36,24 +36,6 @@
<el-icon><ele-Plus /></el-icon>
新增
</el-button>
<el-button size="default" type="warning" @click="onExportTemplate">
<el-icon><ele-Download /></el-icon>
导出模板
</el-button>
<el-upload
ref="uploadRef"
action="#"
:auto-upload="false"
:show-file-list="false"
accept=".xlsx,.xls"
:on-change="handleImportChange"
style="display: inline-block; margin-left: 10px;"
>
<el-button size="default" type="info" :loading="importLoading">
<el-icon><ele-Upload /></el-icon>
导入
</el-button>
</el-upload>
</el-form-item>
</el-form>
</div>
@@ -88,9 +70,9 @@
</el-table-column>
<el-table-column prop="assigneeName" label="负责人" width="100" align="center" />
<el-table-column prop="createdAt" label="创建时间" width="170" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right" align="center">
<el-table-column label="操作" width="150" fixed="right" align="center">
<template #default="scope">
<el-button link type="primary" @click="onOpenImport(scope.row)">导入</el-button>
<el-button link type="danger" @click="onDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
@@ -110,6 +92,7 @@
</el-card>
</div>
<EditInventoryCount ref="editRef" @refresh="getList" />
<ImportDialog ref="importRef" @refresh="getList" />
</div>
</template>
@@ -122,13 +105,12 @@ export default {
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { listInventoryCounts, deleteInventoryCount, completeInventoryCount, cancelInventoryCount, exportInventoryCountTemplate, importInventoryCount } from '/@/api/assets/operation/count';
import type { UploadFile } from 'element-plus';
import { listInventoryCounts, deleteInventoryCount, completeInventoryCount, cancelInventoryCount } from '/@/api/assets/operation/count';
import EditInventoryCount from './component/editInventoryCount.vue';
import ImportDialog from './component/importDialog.vue';
const editRef = ref();
const uploadRef = ref();
const importLoading = ref(false);
const importRef = ref();
const tableData = reactive({
data: [] as any[],
@@ -312,44 +294,9 @@ const onDelete = (row: any) => {
}).catch(() => {});
};
// 导出模板
const onExportTemplate = async () => {
try {
const res = await exportInventoryCountTemplate();
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = '盘点模板.xlsx';
link.click();
window.URL.revokeObjectURL(url);
ElMessage.success('导出成功');
} catch (error) {
console.error('导出模板失败:', error);
ElMessage.error('导出模板失败');
}
};
// 导入文件变化
const handleImportChange = async (file: UploadFile) => {
if (!file.raw) return;
importLoading.value = true;
try {
const res = await importInventoryCount(file.raw);
if (res.data.code === 200) {
ElMessage.success('导入成功');
getList();
} else {
ElMessage.error(res.data.msg || '导入失败');
}
} catch (error) {
console.error('导入失败:', error);
ElMessage.error('导入失败');
} finally {
importLoading.value = false;
uploadRef.value?.clearFiles();
}
// 打开导入弹窗
const onOpenImport = (row: any) => {
importRef.value?.openDialog(row.id);
};
// 分页大小变化