优化库位和库区管理的仓库选择交互,将下拉选择改为弹窗选择模式,新增库位必填字段验证,调整盘点管理导入功能从列表操作移至详情操作,优化查询条件从ID改为名称模糊查询
This commit is contained in:
@@ -101,8 +101,9 @@ export function exportInventoryCountTemplate() {
|
||||
}
|
||||
|
||||
// 上传盘点Excel
|
||||
export function importInventoryCount(file: File) {
|
||||
export function importInventoryCount(id: string, file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append('id', id);
|
||||
formData.append('file', file);
|
||||
return newService({
|
||||
url: 'assets/inventory/count/importInventoryCount',
|
||||
|
||||
141
src/views/assets/component/selectWarehouseDialog.vue
Normal file
141
src/views/assets/component/selectWarehouseDialog.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<el-dialog title="选择仓库" v-model="isShowDialog" width="700px" :close-on-click-modal="false" @close="onCancel">
|
||||
<div class="search-box mb15">
|
||||
<el-input v-model="searchKeyword" placeholder="请输入关键词搜索" clearable style="width: 300px" @keyup.enter="onSearch">
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="onSearch" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading" border highlight-current-row @current-change="onCurrentChange">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="warehouseName" label="仓库名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="warehouseCode" label="编码" width="150" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<div class="mt15" style="text-align: right">
|
||||
<el-pagination
|
||||
v-model:current-page="tableData.param.pageNum"
|
||||
v-model:page-size="tableData.param.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="tableData.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onConfirm">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'selectWarehouseDialog',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { listWarehouses } from '/@/api/assets/warehouse';
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['confirm']);
|
||||
|
||||
// 弹窗状态
|
||||
const isShowDialog = ref(false);
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('');
|
||||
|
||||
// 当前选中的行
|
||||
const currentRow = ref<any>(null);
|
||||
|
||||
// 表格数据
|
||||
const tableData = reactive({
|
||||
data: [] as any[],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
keyword: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
});
|
||||
|
||||
// 获取仓库列表
|
||||
const getWarehouseList = async () => {
|
||||
tableData.loading = true;
|
||||
try {
|
||||
tableData.param.keyword = searchKeyword.value;
|
||||
const res: any = await listWarehouses(tableData.param);
|
||||
tableData.data = res.data?.list || [];
|
||||
tableData.total = res.data?.total || 0;
|
||||
} catch (error) {
|
||||
console.error('获取仓库列表失败:', error);
|
||||
} finally {
|
||||
tableData.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索
|
||||
const onSearch = () => {
|
||||
tableData.param.pageNum = 1;
|
||||
getWarehouseList();
|
||||
};
|
||||
|
||||
// 表格行选中
|
||||
const onCurrentChange = (row: any) => {
|
||||
currentRow.value = row;
|
||||
};
|
||||
|
||||
// 分页大小改变
|
||||
const onSizeChange = (size: number) => {
|
||||
tableData.param.pageSize = size;
|
||||
getWarehouseList();
|
||||
};
|
||||
|
||||
// 当前页改变
|
||||
const onPageChange = (page: number) => {
|
||||
tableData.param.pageNum = page;
|
||||
getWarehouseList();
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = () => {
|
||||
searchKeyword.value = '';
|
||||
currentRow.value = null;
|
||||
tableData.param.pageNum = 1;
|
||||
isShowDialog.value = true;
|
||||
getWarehouseList();
|
||||
};
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
isShowDialog.value = false;
|
||||
};
|
||||
|
||||
// 确定
|
||||
const onConfirm = () => {
|
||||
if (currentRow.value) {
|
||||
emit('confirm', currentRow.value);
|
||||
}
|
||||
isShowDialog.value = false;
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
147
src/views/assets/component/selectZoneDialog.vue
Normal file
147
src/views/assets/component/selectZoneDialog.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<el-dialog title="选择库区" v-model="isShowDialog" width="700px" :close-on-click-modal="false" @close="onCancel">
|
||||
<div class="search-box mb15">
|
||||
<el-input v-model="searchKeyword" placeholder="请输入关键词搜索" clearable style="width: 300px" @keyup.enter="onSearch">
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="onSearch" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading" border highlight-current-row @current-change="onCurrentChange">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="zoneName" label="库区名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="zoneCode" label="编码" width="150" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<div class="mt15" style="text-align: right">
|
||||
<el-pagination
|
||||
v-model:current-page="tableData.param.pageNum"
|
||||
v-model:page-size="tableData.param.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="tableData.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onConfirm">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'selectZoneDialog',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { listZones } from '/@/api/assets/zone';
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['confirm']);
|
||||
|
||||
// 弹窗状态
|
||||
const isShowDialog = ref(false);
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('');
|
||||
|
||||
// 当前选中的行
|
||||
const currentRow = ref<any>(null);
|
||||
|
||||
// 仓库ID
|
||||
const warehouseId = ref('');
|
||||
|
||||
// 表格数据
|
||||
const tableData = reactive({
|
||||
data: [] as any[],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
keyword: '',
|
||||
warehouseId: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
});
|
||||
|
||||
// 获取库区列表
|
||||
const getZoneList = async () => {
|
||||
tableData.loading = true;
|
||||
try {
|
||||
tableData.param.keyword = searchKeyword.value;
|
||||
tableData.param.warehouseId = warehouseId.value;
|
||||
const res: any = await listZones(tableData.param);
|
||||
tableData.data = res.data?.list || [];
|
||||
tableData.total = res.data?.total || 0;
|
||||
} catch (error) {
|
||||
console.error('获取库区列表失败:', error);
|
||||
} finally {
|
||||
tableData.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索
|
||||
const onSearch = () => {
|
||||
tableData.param.pageNum = 1;
|
||||
getZoneList();
|
||||
};
|
||||
|
||||
// 表格行选中
|
||||
const onCurrentChange = (row: any) => {
|
||||
currentRow.value = row;
|
||||
};
|
||||
|
||||
// 分页大小改变
|
||||
const onSizeChange = (size: number) => {
|
||||
tableData.param.pageSize = size;
|
||||
getZoneList();
|
||||
};
|
||||
|
||||
// 当前页改变
|
||||
const onPageChange = (page: number) => {
|
||||
tableData.param.pageNum = page;
|
||||
getZoneList();
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (filterWarehouseId?: string) => {
|
||||
searchKeyword.value = '';
|
||||
currentRow.value = null;
|
||||
tableData.param.pageNum = 1;
|
||||
warehouseId.value = filterWarehouseId || '';
|
||||
isShowDialog.value = true;
|
||||
getZoneList();
|
||||
};
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
isShowDialog.value = false;
|
||||
};
|
||||
|
||||
// 确定
|
||||
const onConfirm = () => {
|
||||
if (currentRow.value) {
|
||||
emit('confirm', currentRow.value);
|
||||
}
|
||||
isShowDialog.value = false;
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -22,16 +22,20 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属仓库" prop="warehouseId">
|
||||
<el-select v-model="ruleForm.warehouseId" placeholder="请选择仓库" clearable style="width: 100%" @change="onWarehouseChange">
|
||||
<el-option v-for="item in warehouseOptions" :key="item.id" :label="item.warehouseName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input v-model="warehouseDisplayName" placeholder="请选择仓库" readonly style="width: 100%" @click="onSelectWarehouse">
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="onSelectWarehouse" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属库区" prop="zoneId">
|
||||
<el-select v-model="ruleForm.zoneId" placeholder="请选择库区" clearable style="width: 100%">
|
||||
<el-option v-for="item in filteredZoneOptions" :key="item.id" :label="item.zoneName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input v-model="zoneDisplayName" placeholder="请先选择仓库" readonly :disabled="!ruleForm.warehouseId" style="width: 100%" @click="onSelectZone">
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="onSelectZone" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -93,6 +97,8 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<SelectWarehouseDialog ref="selectWarehouseRef" @confirm="onWarehouseSelected" />
|
||||
<SelectZoneDialog ref="selectZoneRef" @confirm="onZoneSelected" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -102,10 +108,13 @@ export default {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { createLocation, updateLocation, getLocation, getCapacityUnitType } from '/@/api/assets/location';
|
||||
import SelectWarehouseDialog from '/@/views/assets/component/selectWarehouseDialog.vue';
|
||||
import SelectZoneDialog from '/@/views/assets/component/selectZoneDialog.vue';
|
||||
|
||||
// 定义props
|
||||
const props = defineProps<{
|
||||
@@ -127,6 +136,44 @@ const submitLoading = ref(false);
|
||||
// 容量单位类型选项
|
||||
const capacityUnitTypeOptions = ref<{ label: string; value: string }[]>([]);
|
||||
|
||||
// 仓库选择弹窗ref
|
||||
const selectWarehouseRef = ref();
|
||||
// 库区选择弹窗ref
|
||||
const selectZoneRef = ref();
|
||||
// 仓库显示名称
|
||||
const warehouseDisplayName = ref('');
|
||||
// 库区显示名称
|
||||
const zoneDisplayName = ref('');
|
||||
|
||||
// 打开仓库选择弹窗
|
||||
const onSelectWarehouse = () => {
|
||||
selectWarehouseRef.value?.openDialog();
|
||||
};
|
||||
|
||||
// 打开库区选择弹窗
|
||||
const onSelectZone = () => {
|
||||
if (!ruleForm.warehouseId) {
|
||||
ElMessage.warning('请先选择仓库');
|
||||
return;
|
||||
}
|
||||
selectZoneRef.value?.openDialog(ruleForm.warehouseId);
|
||||
};
|
||||
|
||||
// 仓库选择确认
|
||||
const onWarehouseSelected = (row: any) => {
|
||||
ruleForm.warehouseId = row.id;
|
||||
warehouseDisplayName.value = row.warehouseName;
|
||||
// 清空库区选择
|
||||
ruleForm.zoneId = '';
|
||||
zoneDisplayName.value = '';
|
||||
};
|
||||
|
||||
// 库区选择确认
|
||||
const onZoneSelected = (row: any) => {
|
||||
ruleForm.zoneId = row.id;
|
||||
zoneDisplayName.value = row.zoneName;
|
||||
};
|
||||
|
||||
// 表单数据
|
||||
const ruleForm = reactive({
|
||||
id: '',
|
||||
@@ -142,24 +189,16 @@ const ruleForm = reactive({
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 根据选中的仓库过滤库区选项
|
||||
const filteredZoneOptions = computed(() => {
|
||||
if (!ruleForm.warehouseId) {
|
||||
return props.zoneOptions;
|
||||
}
|
||||
return props.zoneOptions.filter((z: any) => z.warehouseId === ruleForm.warehouseId);
|
||||
});
|
||||
|
||||
// 仓库选择变化时清空库区选择
|
||||
const onWarehouseChange = () => {
|
||||
ruleForm.zoneId = '';
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive<FormRules>({
|
||||
locationName: [{ required: true, message: '请输入库位名称', trigger: 'blur' }],
|
||||
locationCode: [{ required: true, message: '请输入库位编码', trigger: 'blur' }],
|
||||
locationType: [{ required: true, message: '请选择库位类型', trigger: 'change' }],
|
||||
warehouseId: [{ required: true, message: '请选择所属仓库', trigger: 'change' }],
|
||||
zoneId: [{ required: true, message: '请选择所属库区', trigger: 'change' }],
|
||||
capacityUnitType: [{ required: true, message: '请选择容量单位类型', trigger: 'change' }],
|
||||
capacityUnit: [{ required: true, message: '请输入容量单位', trigger: 'blur' }],
|
||||
maxCapacity: [{ required: true, message: '请输入最大容量', trigger: 'blur' }],
|
||||
});
|
||||
|
||||
// 重置表单
|
||||
@@ -175,6 +214,8 @@ const resetForm = () => {
|
||||
ruleForm.capacityUnit = '';
|
||||
ruleForm.maxCapacity = 0;
|
||||
ruleForm.remark = '';
|
||||
warehouseDisplayName.value = '';
|
||||
zoneDisplayName.value = '';
|
||||
};
|
||||
|
||||
// 加载容量单位类型选项
|
||||
@@ -210,6 +251,8 @@ const openDialog = async (row?: any) => {
|
||||
ruleForm.locationType = data.locationType || '';
|
||||
ruleForm.warehouseId = data.warehouseId || '';
|
||||
ruleForm.zoneId = data.zoneId || '';
|
||||
warehouseDisplayName.value = data.warehouseName || '';
|
||||
zoneDisplayName.value = data.zoneName || '';
|
||||
ruleForm.status = data.status || 'idle';
|
||||
ruleForm.capacityUnitType = data.capacityUnitType || '';
|
||||
ruleForm.capacityUnit = data.capacityUnit || '';
|
||||
|
||||
@@ -8,14 +8,10 @@
|
||||
<el-input size="default" v-model="tableData.param.keyword" placeholder="请输入库位名称" clearable style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属仓库">
|
||||
<el-select size="default" v-model="tableData.param.warehouseId" placeholder="请选择仓库" clearable style="width: 180px" @change="onWarehouseChange">
|
||||
<el-option v-for="item in warehouseOptions" :key="item.id" :label="item.warehouseName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input size="default" v-model="tableData.param.warehouseName" placeholder="请输入仓库名称" clearable style="width: 180px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属库区">
|
||||
<el-select size="default" v-model="tableData.param.zoneId" placeholder="请选择库区" clearable style="width: 180px">
|
||||
<el-option v-for="item in filteredZoneOptions" :key="item.id" :label="item.zoneName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input size="default" v-model="tableData.param.zoneName" placeholder="请输入库区名称" clearable style="width: 180px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select size="default" v-model="tableData.param.status" placeholder="请选择状态" clearable style="width: 120px">
|
||||
@@ -90,7 +86,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { listLocations, deleteLocation } from '/@/api/assets/location';
|
||||
import { listWarehouses } from '/@/api/assets/warehouse';
|
||||
@@ -105,8 +101,8 @@ const tableData = reactive({
|
||||
loading: false,
|
||||
param: {
|
||||
keyword: '',
|
||||
warehouseId: '',
|
||||
zoneId: '',
|
||||
warehouseName: '',
|
||||
zoneName: '',
|
||||
status: undefined as string | undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
@@ -118,14 +114,6 @@ const warehouseOptions = ref<any[]>([]);
|
||||
// 库区选项
|
||||
const zoneOptions = ref<any[]>([]);
|
||||
|
||||
// 根据选中的仓库过滤库区选项
|
||||
const filteredZoneOptions = computed(() => {
|
||||
if (!tableData.param.warehouseId) {
|
||||
return zoneOptions.value;
|
||||
}
|
||||
return zoneOptions.value.filter((z: any) => z.warehouseId === tableData.param.warehouseId);
|
||||
});
|
||||
|
||||
// 编辑弹窗ref
|
||||
const editLocationRef = ref();
|
||||
// 日志弹窗ref
|
||||
@@ -151,11 +139,6 @@ const getZoneOptions = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 仓库选择变化时清空库区选择
|
||||
const onWarehouseChange = () => {
|
||||
tableData.param.zoneId = '';
|
||||
};
|
||||
|
||||
// 获取库位列表
|
||||
const getLocationList = async () => {
|
||||
tableData.loading = true;
|
||||
@@ -181,8 +164,8 @@ const getLocationList = async () => {
|
||||
// 重置查询
|
||||
const onResetQuery = () => {
|
||||
tableData.param.keyword = '';
|
||||
tableData.param.warehouseId = '';
|
||||
tableData.param.zoneId = '';
|
||||
tableData.param.warehouseName = '';
|
||||
tableData.param.zoneName = '';
|
||||
tableData.param.status = undefined;
|
||||
tableData.param.pageNum = 1;
|
||||
getLocationList();
|
||||
|
||||
209
src/views/assets/operation/count/component/importDialog.vue
Normal file
209
src/views/assets/operation/count/component/importDialog.vue
Normal 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>
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
// 分页大小变化
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属仓库" prop="warehouseId">
|
||||
<el-select v-model="ruleForm.warehouseId" placeholder="请选择仓库" clearable style="width: 100%">
|
||||
<el-option v-for="item in warehouseOptions" :key="item.id" :label="item.warehouseName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input v-model="warehouseDisplayName" placeholder="请选择仓库" readonly style="width: 100%" @click="onSelectWarehouse">
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="onSelectWarehouse" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@@ -54,6 +56,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<SelectWarehouseDialog ref="selectWarehouseRef" @confirm="onWarehouseSelected" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -65,8 +68,10 @@ export default {
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { createZone, updateZone, getZone } from '/@/api/assets/zone';
|
||||
import SelectWarehouseDialog from '/@/views/assets/component/selectWarehouseDialog.vue';
|
||||
|
||||
// 定义props
|
||||
defineProps<{
|
||||
@@ -84,6 +89,22 @@ const isShowDialog = ref(false);
|
||||
const isEdit = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
|
||||
// 仓库选择弹窗ref
|
||||
const selectWarehouseRef = ref();
|
||||
// 仓库显示名称
|
||||
const warehouseDisplayName = ref('');
|
||||
|
||||
// 打开仓库选择弹窗
|
||||
const onSelectWarehouse = () => {
|
||||
selectWarehouseRef.value?.openDialog();
|
||||
};
|
||||
|
||||
// 仓库选择确认
|
||||
const onWarehouseSelected = (row: any) => {
|
||||
ruleForm.warehouseId = row.id;
|
||||
warehouseDisplayName.value = row.warehouseName;
|
||||
};
|
||||
|
||||
// 表单数据
|
||||
const ruleForm = reactive({
|
||||
id: '',
|
||||
@@ -110,6 +131,7 @@ const resetForm = () => {
|
||||
ruleForm.zoneType = '';
|
||||
ruleForm.warehouseId = '';
|
||||
ruleForm.remark = '';
|
||||
warehouseDisplayName.value = '';
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
@@ -126,6 +148,7 @@ const openDialog = async (row?: any) => {
|
||||
ruleForm.zoneCode = data.zoneCode || '';
|
||||
ruleForm.zoneType = data.zoneType || '';
|
||||
ruleForm.warehouseId = data.warehouseId || '';
|
||||
warehouseDisplayName.value = data.warehouseName || '';
|
||||
ruleForm.remark = data.remark || '';
|
||||
} catch (error) {
|
||||
console.error('获取库区详情失败:', error);
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
<el-input size="default" v-model="tableData.param.keyword" placeholder="请输入库区名称" clearable style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属仓库">
|
||||
<el-select size="default" v-model="tableData.param.warehouseId" placeholder="请选择仓库" clearable style="width: 180px">
|
||||
<el-option v-for="item in warehouseOptions" :key="item.id" :label="item.warehouseName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input size="default" v-model="tableData.param.warehouseName" placeholder="请输入仓库名称" clearable style="width: 180px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select size="default" v-model="tableData.param.status" placeholder="请选择状态" clearable style="width: 120px">
|
||||
@@ -101,7 +99,7 @@ const tableData = reactive({
|
||||
loading: false,
|
||||
param: {
|
||||
keyword: '',
|
||||
warehouseId: '',
|
||||
warehouseName: '',
|
||||
status: undefined as string | undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
@@ -150,7 +148,7 @@ const getZoneList = async () => {
|
||||
// 重置查询
|
||||
const onResetQuery = () => {
|
||||
tableData.param.keyword = '';
|
||||
tableData.param.warehouseId = '';
|
||||
tableData.param.warehouseName = '';
|
||||
tableData.param.status = undefined;
|
||||
tableData.param.pageNum = 1;
|
||||
getZoneList();
|
||||
|
||||
Reference in New Issue
Block a user