Files
xgy-oa/klp-ui/src/views/wms/stock/index.vue
2025-08-01 12:57:30 +08:00

430 lines
15 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 stock-layout">
<!-- 左侧树结构 -->
<div class="stock-tree-col">
<el-card shadow="never" class="stock-tree-card">
<div slot="header" class="stock-tree-title">仓库结构</div>
<el-tree :data="warehouseTreeData" :props="treeProps" node-key="warehouseId" highlight-current
@node-click="handleTreeSelect" :expand-on-click-node="false" :default-expand-all="true" class="stock-tree" />
</el-card>
</div>
<!-- 右侧内容 -->
<div class="stock-main-col">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<!-- 移除仓库筛选项 -->
<el-form-item label="物品类型" prop="itemType">
<el-select v-model="queryParams.itemType" placeholder="请选择物品类型" clearable>
<el-option v-for="dict in dict.type.stock_item_type" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="物料" prop="itemId">
<raw-material-select v-if="queryParams.itemType === 'raw_material'" v-model="queryParams.itemId"
placeholder="请选择原材料" style="width: 100%;" clearable />
<product-select v-else-if="queryParams.itemType === 'product'" v-model="queryParams.itemId"
placeholder="请选择产品" style="width: 100%;" clearable />
<el-input v-else v-model="queryParams.itemId" placeholder="请先选择物品类型" :disabled="true" style="width: 100%;" />
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model="queryParams.unit" 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"
v-hasPermi="['wms:stock:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['wms:stock:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['wms:stock:remove']">删除</el-button>
</el-col> -->
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['wms:stock:export']">导出</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-data-analysis" size="mini" @click="showStockBox">库存分析</el-button>
</el-col> -->
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="stockList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键ID" align="center" prop="stockId" v-if="true" />
<el-table-column label="物品类型" align="center" prop="itemType">
<template slot-scope="scope">
<dict-tag :options="dict.type.stock_item_type" :value="scope.row.itemType" />
</template>
</el-table-column>
<el-table-column label="物品" align="center" prop="itemName">
<template slot-scope="scope">
<ProductInfo v-if="scope.row.itemType === 'product'" :productId="scope.row.itemId">
<template #default="{ product }">
{{ product.productName }}({{ product.productCode }})
</template>
</ProductInfo>
<RawMaterialInfo v-else-if="scope.row.itemType === 'raw_material'" :materialId="scope.row.itemId">
<template #default="{ material }">
{{ material.rawMaterialName }}({{ material.rawMaterialCode }})
</template>
</RawMaterialInfo>
</template>
</el-table-column>
<el-table-column label="BOM">
<template slot-scope="scope">
<BomInfoMini :itemType="scope.row.itemType" :itemId="scope.row.itemId" />
</template>
</el-table-column>
<el-table-column label="库存数量" align="center" prop="quantity" />
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="批次号" align="center" prop="batchNo" />
<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)"
v-hasPermi="['wms:stock:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['wms:stock:remove']">删除</el-button>
</template>
</el-table-column> -->
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改库存对话框保持不变 -->
<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="仓库/库区/库位ID" prop="warehouseId">
<warehouse-select v-model="form.warehouseId" placeholder="请选择仓库/库区/库位" style="width: 100%;" clearable />
</el-form-item>
<el-form-item label="物品类型" prop="itemType">
<el-select v-model="form.itemType" placeholder="请选择物品类型">
<el-option v-for="dict in dict.type.stock_item_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="物品" prop="itemId">
<raw-material-select v-if="form.itemType === 'rawMaterial'" v-model="form.itemId" placeholder="请选择原材料"
style="width: 100%;" clearable />
<product-select v-else-if="form.itemType === 'product'" v-model="form.itemId" placeholder="请选择产品"
style="width: 100%;" clearable />
<el-input v-else v-model="form.itemId" placeholder="请先选择物品类型" :disabled="true" style="width: 100%;" />
</el-form-item>
<el-form-item label="库存数量" prop="quantity">
<el-input v-model="form.quantity" placeholder="请输入库存数量" />
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入单位" />
</el-form-item>
<el-form-item label="批次号" prop="batchNo">
<el-input v-model="form.batchNo" 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>
</div>
</template>
<script>
import { listStock, getStock, delStock, addStock, updateStock } from "@/api/wms/stock";
import { listWarehouse } from "@/api/wms/warehouse";
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import ProductSelect from "@/components/KLPService/ProductSelect";
import WarehouseSelect from "@/components/WarehouseSelect";
import StockBox from './box';
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import BomInfoMini from "@/components/KLPService/Renderer/BomInfoMini";
export default {
name: "Stock",
dicts: ['stock_item_type'],
components: {
WarehouseSelect,
RawMaterialSelect,
ProductSelect,
StockBox,
RawMaterialInfo,
ProductInfo,
BomInfoMini
},
data() {
return {
// 库存分析对话框显示状态
stockBoxVisible: false,
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 库存:原材料/产品与库区/库位的存放关系表格数据
stockList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
warehouseId: undefined,
itemType: undefined,
itemId: undefined,
quantity: undefined,
unit: undefined,
batchNo: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
warehouseId: [
{ required: true, message: "仓库/库区/库位ID不能为空", trigger: "blur" }
],
itemType: [
{ required: true, message: "物品类型不能为空", trigger: "change" }
],
itemId: [
{ required: true, message: "物品ID不能为空", trigger: "blur" }
],
quantity: [
{ required: true, message: "库存数量不能为空", trigger: "blur" }
],
unit: [
{ required: true, message: "单位不能为空", trigger: "blur" }
],
batchNo: [
{ required: true, message: "批次号不能为空", trigger: "blur" }
],
},
// 仓库树数据
warehouseTreeData: [],
treeProps: {
children: 'children',
label: 'warehouseName',
isLeaf: () => false
},
};
},
created() {
this.getWarehouseTree();
this.getList();
},
methods: {
/** 查询库存:原材料/产品与库区/库位的存放关系列表 */
getList() {
this.loading = true;
listStock(this.queryParams).then(response => {
this.stockList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 获取仓库树数据
getWarehouseTree() {
listWarehouse().then(response => {
this.warehouseTreeData = this.handleTree(response.data, 'warehouseId', 'parentId');
});
},
// 处理树结构
handleTree(data, id, parentId) {
const cloneData = JSON.parse(JSON.stringify(data));
return cloneData.filter(father => {
const branchArr = cloneData.filter(child => father[id] === child[parentId]);
if (branchArr.length > 0) father.children = branchArr;
return father[parentId] === 0 || father[parentId] === null;
});
},
// 树节点点击
handleTreeSelect(node) {
this.queryParams.warehouseId = node.warehouseId;
this.queryParams.pageNum = 1;
this.getList();
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
stockId: undefined,
warehouseId: undefined,
itemType: undefined,
itemId: undefined,
quantity: undefined,
unit: undefined,
batchNo: undefined,
remark: undefined,
delFlag: undefined,
createTime: undefined,
createBy: undefined,
updateTime: undefined,
updateBy: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.stockId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加库存:原材料/产品与库区/库位的存放关系";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const stockId = row.stockId || this.ids
getStock(stockId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改库存:原材料/产品与库区/库位的存放关系";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.stockId != null) {
updateStock(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addStock(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const stockIds = row.stockId || this.ids;
this.$modal.confirm('是否确认删除库存:原材料/产品与库区/库位的存放关系编号为"' + stockIds + '"的数据项?').then(() => {
this.loading = true;
return delStock(stockIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('wms/stock/export', {
...this.queryParams
}, `stock_${new Date().getTime()}.xlsx`)
},
/** 显示库存分析图表 */
showStockBox() {
this.stockBoxVisible = true;
this.$nextTick(() => {
this.$refs.stockBoxChart && this.$refs.stockBoxChart.refresh();
});
}
}
};
</script>
<style scoped>
.stock-layout {
height: 100%;
display: flex;
flex-direction: row;
}
.stock-tree-col {
width: 260px;
max-width: 300px;
background: #fff;
border-right: 1px solid #f0f0f0;
height: 100%;
padding-right: 0;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.stock-tree-card {
height: 100%;
border: none;
box-shadow: none;
}
.stock-tree-title {
font-weight: bold;
font-size: 16px;
padding: 8px 0;
}
.stock-tree {
min-height: 500px;
max-height: 80vh;
overflow-y: auto;
}
.stock-main-col {
flex: 1;
padding-left: 24px;
min-width: 0;
display: flex;
flex-direction: column;
}
</style>