Files
klp-oa/klp-ui/src/views/wms/warehouse/real.vue
砂糖 473067220a feat(仓库管理): 实现实际仓库的懒加载功能
- 在WarehouseTree组件中为实际仓库类型添加懒加载支持
- 重构ActualWarehouseSelect组件实现树形选择器的懒加载
- 在real.vue页面中使用懒加载表格展示仓库数据
- 优化表单验证和操作逻辑,提升用户体验
2025-11-24 15:45:08 +08:00

390 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="库位编码" prop="actualWarehouseCode">
<el-input
v-model="queryParams.actualWarehouseCode"
placeholder="请输入实际库区/库位编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="库位名称" prop="actualWarehouseName">
<el-input
v-model="queryParams.actualWarehouseName"
placeholder="请输入实际库区/库位名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="排序号" prop="sortNo">
<el-input
v-model="queryParams.sortNo"
placeholder="请输入同级排序号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="是否启用" prop="isEnabled">
<el-input
v-model="queryParams.isEnabled"
placeholder="请输入是否启用"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-sort"
size="mini"
@click="toggleExpandAll"
>展开/折叠</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 懒加载树形表格核心配置lazy + load + ref -->
<el-table
ref="treeTable"
v-loading="loading"
:data="actualWarehouseList"
row-key="actualWarehouseId"
lazy
:load="loadChildren"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
<el-table-column label="库位编码" align="center" prop="actualWarehouseCode" />
<el-table-column label="库位名称" align="center" prop="actualWarehouseName" />
<el-table-column label="占用状态" align="center" prop="isEnabled">
<template slot-scope="scope">
<el-tag :type="scope.row.isEnabled === 1 ? 'success' : 'danger'">
{{ scope.row.isEnabled === 1 ? '空闲' : '占用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="同级排序号" align="center" prop="sortNo" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
>新增</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改实际库区/库位自关联对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="父节点" prop="parentId">
<ActualWarehouseSelect v-model="form.parentId"></ActualWarehouseSelect>
<!-- <treeselect :max-height="200" v-model="form.parentId" :options="actualWarehouseOptions" :normalizer="normalizer" placeholder="请选择父节点ID" /> -->
</el-form-item>
<el-form-item label="库位编码" prop="actualWarehouseCode">
<el-input v-model="form.actualWarehouseCode" placeholder="请输入实际库区/库位编码" />
</el-form-item>
<el-form-item label="库位名称" prop="actualWarehouseName">
<el-input v-model="form.actualWarehouseName" placeholder="请输入实际库区/库位名称" />
</el-form-item>
<el-form-item label="排序" prop="sortNo">
<el-input v-model="form.sortNo" type="number" placeholder="请输入同级排序号" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listActualWarehouse, getActualWarehouse, delActualWarehouse, addActualWarehouse, updateActualWarehouse } from "@/api/wms/actualWarehouse";
// import Treeselect from "@riophae/vue-treeselect";
// import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
export default {
name: "ActualWarehouse",
components: {
// Treeselect,
ActualWarehouseSelect
},
data() {
return {
// 按钮loading
buttonLoading: false,
// 遮罩层(仅控制根节点加载)
loading: true,
// 显示搜索条件
showSearch: true,
// 根节点数据(懒加载模式下仅存储当前层级数据)
actualWarehouseList: [],
// 实际库区/库位自关联树选项
actualWarehouseOptions: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 是否全部展开(懒加载下仅控制已加载节点)
isExpandAll: false,
// 查询参数核心parentId用于懒加载子节点
queryParams: {
parentId: 0, // 初始加载根节点parentId=0
actualWarehouseCode: undefined,
actualWarehouseName: undefined,
actualWarehouseType: undefined,
sortNo: undefined,
isEnabled: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
actualWarehouseCode: [{ required: true, message: "请输入库位编码", trigger: "blur" }],
actualWarehouseName: [{ required: true, message: "请输入库位名称", trigger: "blur" }],
sortNo: [{ required: true, type: "number", message: "请输入有效排序号", trigger: "blur" }]
}
};
},
created() {
this.getList(); // 初始加载根节点
},
methods: {
/** 加载根节点数据parentId=0 */
getList() {
this.loading = true;
// 强制设置parentId=0加载根节点
this.queryParams.parentId = 0;
listActualWarehouse(this.queryParams).then(response => {
// 为根节点添加hasChildren标识后端未返回时默认true确保显示展开按钮
this.actualWarehouseList = response.data.map(node => ({
...node,
hasChildren: node.hasChildren ?? true // 双问号兼容null/undefined
}));
this.loading = false;
}).catch(() => {
this.loading = false;
});
},
/** 懒加载子节点核心方法Element UI自带回调 */
loadChildren(treeData, treeNode, resolve) {
// treeNode当前展开的父节点对象treeNode.data为父节点数据
console.log(treeNode, resolve);
const parentId = treeData.actualWarehouseId;
// 构造子节点查询参数继承当前查询条件仅修改parentId
const childParams = {
...this.queryParams,
parentId: parentId // 关键用父节点ID作为子节点查询条件
};
// 显示节点加载状态
treeNode.loading = true;
// 调用接口加载子节点
listActualWarehouse(childParams).then(response => {
const children = response.data.map(node => ({
...node,
hasChildren: node.hasChildren ?? false // 子节点默认可能无下级,根据实际业务调整
}));
treeNode.loading = false;
resolve(children); // 回调返回子节点数据,表格自动渲染
}).catch(() => {
treeNode.loading = false;
resolve([]); // 加载失败返回空数组
});
},
/** 转换实际库区/库位自关联数据结构(下拉树用) */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children;
}
return {
id: node.actualWarehouseId,
label: node.actualWarehouseName,
children: node.children
};
},
// /** 查询实际库区/库位自关联下拉树结构 */
// getTreeselect() {
// listActualWarehouse().then(response => {
// this.actualWarehouseOptions = [];
// const data = { actualWarehouseId: 0, actualWarehouseName: '顶级节点', children: [] };
// data.children = this.handleTree(response.data, "actualWarehouseId", "parentId");
// this.actualWarehouseOptions.push(data);
// });
// },
// 树形结构处理(仅下拉树用,懒加载表格无需)
handleTree(data, id, parentId, children = 'children') {
const result = [];
const map = {};
data.forEach(item => {
map[item[id]] = item;
});
data.forEach(item => {
const parent = map[item[parentId]];
if (parent) {
(parent[children] || (parent[children] = [])).push(item);
} else {
result.push(item);
}
});
return result;
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
actualWarehouseId: null,
parentId: 0, // 默认顶级节点
actualWarehouseCode: null,
actualWarehouseName: null,
actualWarehouseType: 1,
sortNo: 0,
isEnabled: null,
delFlag: null,
remark: null
};
this.resetForm("form");
},
/** 搜索按钮操作(重新加载根节点 + 清空已加载子节点) */
handleQuery() {
this.getList();
// 清空表格已加载的子节点缓存
if (this.$refs.treeTable) {
this.$refs.treeTable.store.clearNodes();
}
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd(row) {
this.reset();
// this.getTreeselect();
// 若从节点操作栏点击新增设置父节点为当前节点ID
if (row?.actualWarehouseId) {
this.form.parentId = row.actualWarehouseId;
}
this.open = true;
this.title = "添加实际库区/库位自关联";
},
/** 展开/折叠所有已加载节点 */
toggleExpandAll() {
const treeTable = this.$refs.treeTable;
if (!treeTable) return;
this.isExpandAll = !this.isExpandAll;
if (this.isExpandAll) {
treeTable.expandAll(); // 展开所有已加载节点
} else {
treeTable.collapseAll(); // 折叠所有节点
}
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
// this.getTreeselect();
getActualWarehouse(row.actualWarehouseId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改实际库区/库位自关联";
}).catch(() => {
this.loading = false;
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
const request = this.form.actualWarehouseId
? updateActualWarehouse(this.form)
: addActualWarehouse(this.form);
request.then(response => {
this.$modal.msgSuccess(this.form.actualWarehouseId ? "修改成功" : "新增成功");
this.open = false;
this.getList(); // 新增/修改后刷新根节点
}).catch(() => {
this.$modal.msgError(this.form.actualWarehouseId ? "修改失败" : "新增失败");
}).finally(() => {
this.buttonLoading = false;
});
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal.confirm(`是否确认删除实际库区/库位自关联【${row.actualWarehouseName}】?`).then(() => {
return delActualWarehouse(row.actualWarehouseId);
}).then(() => {
this.getList(); // 删除后刷新根节点
if (this.$refs.treeTable) {
this.$refs.treeTable.store.clearNodes();
}
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
}
};
</script>